diff options
Diffstat (limited to 'board/pcippc2')
-rwxr-xr-x | board/pcippc2/Makefile | 45 | ||||
-rwxr-xr-x | board/pcippc2/config.mk | 30 | ||||
-rwxr-xr-x | board/pcippc2/cpc710.h | 96 | ||||
-rwxr-xr-x | board/pcippc2/cpc710_init_ram.c | 254 | ||||
-rwxr-xr-x | board/pcippc2/cpc710_pci.c | 309 | ||||
-rwxr-xr-x | board/pcippc2/cpc710_pci.h | 51 | ||||
-rwxr-xr-x | board/pcippc2/flash.c | 573 | ||||
-rwxr-xr-x | board/pcippc2/fpga_serial.c | 132 | ||||
-rwxr-xr-x | board/pcippc2/fpga_serial.h | 34 | ||||
-rwxr-xr-x | board/pcippc2/hardware.h | 48 | ||||
-rwxr-xr-x | board/pcippc2/i2c.c | 257 | ||||
-rwxr-xr-x | board/pcippc2/i2c.h | 36 | ||||
-rwxr-xr-x | board/pcippc2/ns16550.h | 41 | ||||
-rwxr-xr-x | board/pcippc2/pcippc2.c | 245 | ||||
-rwxr-xr-x | board/pcippc2/pcippc2.h | 51 | ||||
-rwxr-xr-x | board/pcippc2/pcippc2_fpga.c | 87 | ||||
-rwxr-xr-x | board/pcippc2/pcippc2_fpga.h | 49 | ||||
-rwxr-xr-x | board/pcippc2/sconsole.c | 141 | ||||
-rwxr-xr-x | board/pcippc2/sconsole.h | 49 | ||||
-rwxr-xr-x | board/pcippc2/u-boot.lds | 141 |
20 files changed, 2669 insertions, 0 deletions
diff --git a/board/pcippc2/Makefile b/board/pcippc2/Makefile new file mode 100755 index 0000000..2998f23 --- /dev/null +++ b/board/pcippc2/Makefile @@ -0,0 +1,45 @@ +# +# (C) Copyright 2002 +# 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 + +COBJS = $(BOARD).o cpc710_pci.o flash.o sconsole.o \ + fpga_serial.o pcippc2_fpga.o cpc710_init_ram.o i2c.o + +AOBJS = + +OBJS = $(COBJS) $(AOBJS) + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(AOBJS:.o=.S) $(COBJS:.o=.c) + $(CC) -M $(CFLAGS) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/pcippc2/config.mk b/board/pcippc2/config.mk new file mode 100755 index 0000000..92d37c9 --- /dev/null +++ b/board/pcippc2/config.mk @@ -0,0 +1,30 @@ +# +# (C) Copyright 2002 +# 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 +# + +# +# PCIPPC-2 boards +# + +TEXT_BASE = 0xfff00000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) diff --git a/board/pcippc2/cpc710.h b/board/pcippc2/cpc710.h new file mode 100755 index 0000000..8167270 --- /dev/null +++ b/board/pcippc2/cpc710.h @@ -0,0 +1,96 @@ +/* + * (C) Copyright 2002 + * 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 _CPC710_H_ +#define _CPC710_H_ + +/* Revision */ +#define CPC710_TYPE_100 0x80 +#define CPC710_TYPE_100P 0x90 + +/* System control area */ +#define HW_PHYS_SCA 0xff000000 + +#define HW_SCA_CPC0 0x000000 +#define HW_SCA_SDRAM0 0x000000 +#define HW_SCA_DMA0 0x1C0000 + +#define HW_PHYS_CPC0 (HW_PHYS_SCA + HW_SCA_CPC0) +#define HW_PHYS_SDRAM0 (HW_PHYS_SCA + HW_SCA_SDRAM0) + +#define HW_CPC0_PCICNFR 0x000c +#define HW_CPC0_RSTR 0x0010 +#define HW_CPC0_SPOR 0x00e8 +#define HW_CPC0_UCTL 0x1000 +#define HW_CPC0_SIOC0 0x1020 +#define HW_CPC0_ABCNTL 0x1030 +#define HW_CPC0_SESR 0x1060 +#define HW_CPC0_SEAR 0x1070 +#define HW_CPC0_PGCHP 0x1100 +#define HW_CPC0_RGBAN0 0x1110 +#define HW_CPC0_RGBAN1 0x1120 + +#define HW_CPC0_GPDIR 0x1130 +#define HW_CPC0_GPIN 0x1140 +#define HW_CPC0_GPOUT 0x1150 + +#define HW_CPC0_ATAS 0x1160 + +#define HW_CPC0_PCIBAR 0x200018 +#define HW_CPC0_PCIENB 0x201000 + +#define HW_SDRAM0_MCCR 0x1200 +#define HW_SDRAM0_MESR 0x1220 +#define HW_SDRAM0_MEAR 0x1230 + +#define HW_SDRAM0_MCER0 0x1300 +#define HW_SDRAM0_MCER1 0x1310 +#define HW_SDRAM0_MCER2 0x1320 +#define HW_SDRAM0_MCER3 0x1330 +#define HW_SDRAM0_MCER4 0x1340 +#define HW_SDRAM0_MCER5 0x1350 +#define HW_SDRAM0_MCER6 0x1360 +#define HW_SDRAM0_MCER7 0x1370 + +#define HW_BRIDGE_PCIDG 0xf6120 +#define HW_BRIDGE_INTACK 0xf7700 +#define HW_BRIDGE_PIBAR 0xf7800 +#define HW_BRIDGE_PMBAR 0xf7810 +#define HW_BRIDGE_CRR 0xf7ef0 +#define HW_BRIDGE_PR 0xf7f20 +#define HW_BRIDGE_ACR 0xf7f30 +#define HW_BRIDGE_MSIZE 0xf7f40 +#define HW_BRIDGE_IOSIZE 0xf7f60 +#define HW_BRIDGE_SMBAR 0xf7f80 +#define HW_BRIDGE_SIBAR 0xf7fc0 +#define HW_BRIDGE_CFGADDR 0xf8000 +#define HW_BRIDGE_CFGDATA 0xf8010 +#define HW_BRIDGE_PSSIZE 0xf8100 +#define HW_BRIDGE_BARPS 0xf8120 +#define HW_BRIDGE_PSBAR 0xf8140 + +/* Configuration space registers */ +#define CPC710_BUS_NUMBER 0x40 +#define CPC710_SUB_BUS_NUMBER 0x41 + +#endif diff --git a/board/pcippc2/cpc710_init_ram.c b/board/pcippc2/cpc710_init_ram.c new file mode 100755 index 0000000..57ed8f0 --- /dev/null +++ b/board/pcippc2/cpc710_init_ram.c @@ -0,0 +1,254 @@ +/* + * (C) Copyright 2002 + * 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> +#include <common.h> +#include <asm/io.h> + +#include "pcippc2.h" +#include "i2c.h" + +typedef struct cpc710_mem_org_s +{ + u8 rows; + u8 cols; + u8 banks2; + u8 org; +} cpc710_mem_org_t; + +static int cpc710_compute_mcer (u32 * mcer, + unsigned long * + size, + unsigned int sdram); +static int cpc710_eeprom_checksum (unsigned int sdram); +static u8 cpc710_eeprom_read (unsigned int sdram, + unsigned int offset); + +static u32 cpc710_mcer_mem [] = +{ + 0x000003f3, /* 18 lines, 4 Mb */ + 0x000003e3, /* 19 lines, 8 Mb */ + 0x000003c3, /* 20 lines, 16 Mb */ + 0x00000383, /* 21 lines, 32 Mb */ + 0x00000303, /* 22 lines, 64 Mb */ + 0x00000203, /* 23 lines, 128 Mb */ + 0x00000003, /* 24 lines, 256 Mb */ + 0x00000002, /* 25 lines, 512 Mb */ + 0x00000001 /* 26 lines, 1024 Mb */ +}; +static cpc710_mem_org_t cpc710_mem_org [] = +{ + { 0x0c, 0x09, 0x02, 0x00 }, /* 0000: 12/ 9/2 */ + { 0x0d, 0x09, 0x02, 0x00 }, /* 0000: 13/ 9/2 */ + { 0x0d, 0x0a, 0x02, 0x00 }, /* 0000: 13/10/2 */ + { 0x0d, 0x0b, 0x02, 0x00 }, /* 0000: 13/11/2 */ + { 0x0d, 0x0c, 0x02, 0x00 }, /* 0000: 13/12/2 */ + { 0x0e, 0x0c, 0x02, 0x00 }, /* 0000: 14/12/2 */ + { 0x0b, 0x08, 0x02, 0x01 }, /* 0001: 11/ 8/2 */ + { 0x0b, 0x09, 0x01, 0x02 }, /* 0010: 11/ 9/1 */ + { 0x0b, 0x0a, 0x01, 0x03 }, /* 0011: 11/10/1 */ + { 0x0c, 0x08, 0x02, 0x04 }, /* 0100: 12/ 8/2 */ + { 0x0c, 0x0a, 0x02, 0x05 }, /* 0101: 12/10/2 */ + { 0x0d, 0x08, 0x01, 0x06 }, /* 0110: 13/ 8/1 */ + { 0x0d, 0x08, 0x02, 0x07 }, /* 0111: 13/ 8/2 */ + { 0x0d, 0x09, 0x01, 0x08 }, /* 1000: 13/ 9/1 */ + { 0x0d, 0x0a, 0x01, 0x09 }, /* 1001: 13/10/1 */ + { 0x0b, 0x08, 0x01, 0x0a }, /* 1010: 11/ 8/1 */ + { 0x0c, 0x08, 0x01, 0x0b }, /* 1011: 12/ 8/1 */ + { 0x0c, 0x09, 0x01, 0x0c }, /* 1100: 12/ 9/1 */ + { 0x0e, 0x09, 0x02, 0x0d }, /* 1101: 14/ 9/2 */ + { 0x0e, 0x0a, 0x02, 0x0e }, /* 1110: 14/10/2 */ + { 0x0e, 0x0b, 0x02, 0x0f } /* 1111: 14/11/2 */ +}; + +unsigned long cpc710_ram_init (void) +{ + unsigned long memsize = 0; + unsigned long bank_size; + u32 mcer; + +#ifndef CFG_RAMBOOT + /* Clear memory banks + */ + out32(REG(SDRAM0, MCER0), 0); + out32(REG(SDRAM0, MCER1), 0); + out32(REG(SDRAM0, MCER2), 0); + out32(REG(SDRAM0, MCER3), 0); + out32(REG(SDRAM0, MCER4), 0); + out32(REG(SDRAM0, MCER5), 0); + out32(REG(SDRAM0, MCER6), 0); + out32(REG(SDRAM0, MCER7), 0); + iobarrier_rw(); + + /* Disable memory + */ + out32(REG(SDRAM0,MCCR), 0x13b06000); + iobarrier_rw(); +#endif + + /* Only the first memory bank is initialised now + */ + if (! cpc710_compute_mcer(& mcer, & bank_size, 0)) + { + puts("Unsupported SDRAM type !\n"); + hang(); + } + memsize += bank_size; +#ifndef CFG_RAMBOOT + /* Enable bank, zero start + */ + out32(REG(SDRAM0, MCER0), mcer | 0x80000000); + iobarrier_rw(); +#endif + +#ifndef CFG_RAMBOOT + /* Enable memory + */ + out32(REG(SDRAM0, MCCR), in32(REG(SDRAM0, MCCR)) | 0x80000000); + + /* Wait until initialisation finished + */ + while (! (in32 (REG(SDRAM0, MCCR)) & 0x20000000)) + { + iobarrier_rw(); + } + + /* Clear Memory Error Status and Address registers + */ + out32(REG(SDRAM0, MESR), 0); + out32(REG(SDRAM0, MEAR), 0); + iobarrier_rw(); + + /* ECC is not configured now + */ +#endif + + /* Memory size counter + */ + out32(REG(CPC0, RGBAN1), memsize); + + return memsize; +} + +static int cpc710_compute_mcer ( + u32 * mcer, + unsigned long * size, + unsigned int sdram) +{ + u8 rows; + u8 cols; + u8 banks2; + unsigned int lines; + u32 mc = 0; + unsigned int i; + cpc710_mem_org_t * org = 0; + + + if (! i2c_reset()) + { + puts("Can't reset I2C!\n"); + hang(); + } + + if (! cpc710_eeprom_checksum(sdram)) + { + puts("Invalid EEPROM checksum !\n"); + hang(); + } + + rows = cpc710_eeprom_read(sdram, 3); + cols = cpc710_eeprom_read(sdram, 4); + /* Can be 2 or 4 banks; divide by 2 + */ + banks2 = cpc710_eeprom_read(sdram, 17) / 2; + + lines = rows + cols + banks2; + + if (lines < 18 || lines > 26) + { + /* Unsupported configuration + */ + return 0; + } + + + mc |= cpc710_mcer_mem [lines - 18] << 6; + + for (i = 0; i < sizeof(cpc710_mem_org) / sizeof(cpc710_mem_org_t); i++) + { + cpc710_mem_org_t * corg = cpc710_mem_org + i; + + if (corg->rows == rows && corg->cols == cols && corg->banks2 == banks2) + { + org = corg; + + break; + } + } + + if (! org) + { + /* Unsupported configuration + */ + return 0; + } + + mc |= (u32) org->org << 2; + + /* Supported configuration + */ + *mcer = mc; + *size = 1l << (lines + 4); + + return 1; +} + +static int cpc710_eeprom_checksum ( + unsigned int sdram) +{ + u8 sum = 0; + unsigned int i; + + for (i = 0; i < 63; i++) + { + sum += cpc710_eeprom_read(sdram, i); + } + + return sum == cpc710_eeprom_read(sdram, 63); +} + +static u8 cpc710_eeprom_read ( + unsigned int sdram, + unsigned int offset) +{ + u8 dev = (sdram << 1) | 0xa0; + u8 data; + + if (! i2c_read_byte(& data, dev,offset)) + { + puts("I2C error !\n"); + hang(); + } + + return data; +} diff --git a/board/pcippc2/cpc710_pci.c b/board/pcippc2/cpc710_pci.c new file mode 100755 index 0000000..bed8aea --- /dev/null +++ b/board/pcippc2/cpc710_pci.c @@ -0,0 +1,309 @@ +/* + * (C) Copyright 2002 + * 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> +#include <common.h> +#include <asm/io.h> +#include <pci.h> + +#include "hardware.h" +#include "pcippc2.h" + +struct pci_controller local_hose, cpci_hose; + +static u32 cpc710_mapped_ram; + + /* Enable PCI retry timeouts + */ +void cpc710_pci_enable_timeout (void) +{ + out32(BRIDGE(LOCAL, CFGADDR), 0x50000080); + iobarrier_rw(); + out32(BRIDGE(LOCAL, CFGDATA), 0x32000000); + iobarrier_rw(); + + out32(BRIDGE(CPCI, CFGADDR), 0x50000180); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), 0x32000000); + iobarrier_rw(); +} + +void cpc710_pci_init (void) +{ + u32 sdram_size = pcippc2_sdram_size(); + + cpc710_mapped_ram = sdram_size < PCI_MEMORY_MAXSIZE ? + sdram_size : PCI_MEMORY_MAXSIZE; + + /* Select the local PCI + */ + out32(REG(CPC0, PCICNFR), 0x80000002); + iobarrier_rw(); + + out32(REG(CPC0, PCIBAR), BRIDGE_LOCAL_PHYS); + iobarrier_rw(); + + /* Enable PCI bridge address decoding + */ + out32(REG(CPC0, PCIENB), 0x80000000); + iobarrier_rw(); + + /* Select the CPCI bridge + */ + out32(REG(CPC0, PCICNFR), 0x80000003); + iobarrier_rw(); + + out32(REG(CPC0, PCIBAR), BRIDGE_CPCI_PHYS); + iobarrier_rw(); + + /* Enable PCI bridge address decoding + */ + out32(REG(CPC0, PCIENB), 0x80000000); + iobarrier_rw(); + + /* Disable configuration accesses + */ + out32(REG(CPC0, PCICNFR), 0x80000000); + iobarrier_rw(); + + /* Initialise the local PCI + */ + out32(BRIDGE(LOCAL, CRR), 0x7c000000); + iobarrier_rw(); + out32(BRIDGE(LOCAL, PCIDG), 0x40000000); + iobarrier_rw(); + out32(BRIDGE(LOCAL, PIBAR), BRIDGE_LOCAL_IO_BUS); + out32(BRIDGE(LOCAL, SIBAR), BRIDGE_LOCAL_IO_PHYS); + out32(BRIDGE(LOCAL, IOSIZE), -BRIDGE_LOCAL_IO_SIZE); + iobarrier_rw(); + out32(BRIDGE(LOCAL, PMBAR), BRIDGE_LOCAL_MEM_BUS); + out32(BRIDGE(LOCAL, SMBAR), BRIDGE_LOCAL_MEM_PHYS); + out32(BRIDGE(LOCAL, MSIZE), -BRIDGE_LOCAL_MEM_SIZE); + iobarrier_rw(); + out32(BRIDGE(LOCAL, PR), 0x00ffe000); + iobarrier_rw(); + out32(BRIDGE(LOCAL, ACR), 0xfe000000); + iobarrier_rw(); + out32(BRIDGE(LOCAL, PSBAR), PCI_MEMORY_BUS >> 24); + out32(BRIDGE(LOCAL, BARPS), PCI_MEMORY_PHYS >> 24); + out32(BRIDGE(LOCAL, PSSIZE), 256 - (cpc710_mapped_ram >> 24)); + iobarrier_rw(); + + /* Initialise the CPCI bridge + */ + out32(BRIDGE(CPCI, CRR), 0x7c000000); + iobarrier_rw(); + out32(BRIDGE(CPCI, PCIDG), 0xC0000000); + iobarrier_rw(); + out32(BRIDGE(CPCI, PIBAR), BRIDGE_CPCI_IO_BUS); + out32(BRIDGE(CPCI, SIBAR), BRIDGE_CPCI_IO_PHYS); + out32(BRIDGE(CPCI, IOSIZE), -BRIDGE_CPCI_IO_SIZE); + iobarrier_rw(); + out32(BRIDGE(CPCI, PMBAR), BRIDGE_CPCI_MEM_BUS); + out32(BRIDGE(CPCI, SMBAR), BRIDGE_CPCI_MEM_PHYS); + out32(BRIDGE(CPCI, MSIZE), -BRIDGE_CPCI_MEM_SIZE); + iobarrier_rw(); + out32(BRIDGE(CPCI, PR), 0x80ffe000); + iobarrier_rw(); + out32(BRIDGE(CPCI, ACR), 0xdf000000); + iobarrier_rw(); + out32(BRIDGE(CPCI, PSBAR), PCI_MEMORY_BUS >> 24); + out32(BRIDGE(CPCI, BARPS), PCI_MEMORY_PHYS >> 24); + out32(BRIDGE(CPCI, PSSIZE), 256 - (cpc710_mapped_ram >> 24)); + iobarrier_rw(); + + /* Local PCI + */ + + out32(BRIDGE(LOCAL, CFGADDR), 0x04000080); + iobarrier_rw(); + out32(BRIDGE(LOCAL, CFGDATA), 0x56010000); + iobarrier_rw(); + + out32(BRIDGE(LOCAL, CFGADDR), 0x0c000080); + iobarrier_rw(); + out32(BRIDGE(LOCAL, CFGDATA), PCI_LATENCY_TIMER_VAL << 16); + iobarrier_rw(); + + /* Set bus and subbus numbers + */ + out32(BRIDGE(LOCAL, CFGADDR), 0x40000080); + iobarrier_rw(); + out32(BRIDGE(LOCAL, CFGDATA), 0x00000000); + iobarrier_rw(); + + out32(BRIDGE(LOCAL, CFGADDR), 0x50000080); + iobarrier_rw(); + /* PCI retry timeouts will be enabled later + */ + out32(BRIDGE(LOCAL, CFGDATA), 0x00000000); + iobarrier_rw(); + + /* CPCI + */ + + /* Set bus and subbus numbers + */ + out32(BRIDGE(CPCI, CFGADDR), 0x40000080); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), 0x01010000); + iobarrier_rw(); + + out32(BRIDGE(CPCI, CFGADDR), 0x04000180); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), 0x56010000); + iobarrier_rw(); + + out32(BRIDGE(CPCI, CFGADDR), 0x0c000180); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), PCI_LATENCY_TIMER_VAL << 16); + iobarrier_rw(); + + /* Write to the PSBAR */ + out32(BRIDGE(CPCI, CFGADDR), 0x10000180); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), cpu_to_le32(PCI_MEMORY_BUS)); + iobarrier_rw(); + + /* Set bus and subbus numbers + */ + out32(BRIDGE(CPCI, CFGADDR), 0x40000180); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), 0x01ff0000); + iobarrier_rw(); + + out32(BRIDGE(CPCI, CFGADDR), 0x50000180); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), 0x32000000); + /* PCI retry timeouts will be enabled later + */ + out32(BRIDGE(CPCI, CFGDATA), 0x00000000); + iobarrier_rw(); + + /* Remove reset on the PCI buses + */ + out32(BRIDGE(LOCAL, CRR), 0xfc000000); + iobarrier_rw(); + out32(BRIDGE(CPCI, CRR), 0xfc000000); + iobarrier_rw(); + + local_hose.first_busno = 0; + local_hose.last_busno = 0xff; + + /* System memory space */ + pci_set_region(local_hose.regions + 0, + PCI_MEMORY_BUS, + PCI_MEMORY_PHYS, + PCI_MEMORY_MAXSIZE, + PCI_REGION_MEM | PCI_REGION_MEMORY); + + /* PCI memory space */ + pci_set_region(local_hose.regions + 1, + BRIDGE_LOCAL_MEM_BUS, + BRIDGE_LOCAL_MEM_PHYS, + BRIDGE_LOCAL_MEM_SIZE, + PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region(local_hose.regions + 2, + BRIDGE_LOCAL_IO_BUS, + BRIDGE_LOCAL_IO_PHYS, + BRIDGE_LOCAL_IO_SIZE, + PCI_REGION_IO); + + local_hose.region_count = 3; + + pci_setup_indirect(&local_hose, + BRIDGE_LOCAL_PHYS + HW_BRIDGE_CFGADDR, + BRIDGE_LOCAL_PHYS + HW_BRIDGE_CFGDATA); + + pci_register_hose(&local_hose); + + /* Initialize PCI32 bus registers */ + pci_hose_write_config_byte(&local_hose, + PCI_BDF(local_hose.first_busno,0,0), + CPC710_BUS_NUMBER, + local_hose.first_busno); + pci_hose_write_config_byte(&local_hose, + PCI_BDF(local_hose.first_busno,0,0), + CPC710_SUB_BUS_NUMBER, + local_hose.last_busno); + + local_hose.last_busno = pci_hose_scan(&local_hose); + + /* Write out correct max subordinate bus number for local hose */ + pci_hose_write_config_byte(&local_hose, + PCI_BDF(local_hose.first_busno,0,0), + CPC710_SUB_BUS_NUMBER, + local_hose.last_busno); + + cpci_hose.first_busno = local_hose.last_busno + 1; + cpci_hose.last_busno = 0xff; + + /* System memory space */ + pci_set_region(cpci_hose.regions + 0, + PCI_MEMORY_BUS, + PCI_MEMORY_PHYS, + PCI_MEMORY_MAXSIZE, + PCI_REGION_MEMORY); + + /* PCI memory space */ + pci_set_region(cpci_hose.regions + 1, + BRIDGE_CPCI_MEM_BUS, + BRIDGE_CPCI_MEM_PHYS, + BRIDGE_CPCI_MEM_SIZE, + PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region(cpci_hose.regions + 2, + BRIDGE_CPCI_IO_BUS, + BRIDGE_CPCI_IO_PHYS, + BRIDGE_CPCI_IO_SIZE, + PCI_REGION_IO); + + cpci_hose.region_count = 3; + + pci_setup_indirect(&cpci_hose, + BRIDGE_CPCI_PHYS + HW_BRIDGE_CFGADDR, + BRIDGE_CPCI_PHYS + HW_BRIDGE_CFGDATA); + + pci_register_hose(&cpci_hose); + + /* Initialize PCI64 bus registers */ + pci_hose_write_config_byte(&cpci_hose, + PCI_BDF(cpci_hose.first_busno,0,0), + CPC710_BUS_NUMBER, + cpci_hose.first_busno); + pci_hose_write_config_byte(&cpci_hose, + PCI_BDF(cpci_hose.first_busno,0,0), + CPC710_SUB_BUS_NUMBER, + cpci_hose.last_busno); + + cpci_hose.last_busno = pci_hose_scan(&cpci_hose); + + /* Write out correct max subordinate bus number for cpci hose */ + pci_hose_write_config_byte(&cpci_hose, + PCI_BDF(cpci_hose.first_busno,0,0), + CPC710_SUB_BUS_NUMBER, + cpci_hose.last_busno); +} diff --git a/board/pcippc2/cpc710_pci.h b/board/pcippc2/cpc710_pci.h new file mode 100755 index 0000000..24d0db6 --- /dev/null +++ b/board/pcippc2/cpc710_pci.h @@ -0,0 +1,51 @@ +/* + * (C) Copyright 2002 + * 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 _CPC710_PCI_H_ +#define _CPC710_PCI_H_ + +#define PCI_MEMORY_PHYS 0x00000000 +#define PCI_MEMORY_BUS 0x80000000 +#define PCI_MEMORY_MAXSIZE 0x20000000 + +#define BRIDGE_CPCI_PHYS 0xff500000 +#define BRIDGE_CPCI_MEM_SIZE 0x08000000 +#define BRIDGE_CPCI_MEM_PHYS 0xf0000000 +#define BRIDGE_CPCI_MEM_BUS 0x00000000 +#define BRIDGE_CPCI_IO_SIZE 0x02000000 +#define BRIDGE_CPCI_IO_PHYS 0xfc000000 +#define BRIDGE_CPCI_IO_BUS 0x00000000 + +#define BRIDGE_LOCAL_PHYS 0xff400000 +#define BRIDGE_LOCAL_MEM_SIZE 0x04000000 +#define BRIDGE_LOCAL_MEM_PHYS 0xf8000000 +#define BRIDGE_LOCAL_MEM_BUS 0x40000000 +#define BRIDGE_LOCAL_IO_SIZE 0x01000000 +#define BRIDGE_LOCAL_IO_PHYS 0xfe000000 +#define BRIDGE_LOCAL_IO_BUS 0x04000000 + +#define BRIDGE(r, x) (BRIDGE_##r##_PHYS + HW_BRIDGE_##x) + +#define PCI_LATENCY_TIMER_VAL 0xff + +#endif diff --git a/board/pcippc2/flash.c b/board/pcippc2/flash.c new file mode 100755 index 0000000..8c01415 --- /dev/null +++ b/board/pcippc2/flash.c @@ -0,0 +1,573 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * (C) Copyright 2002 + * 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> +#include <common.h> +#include <flash.h> +#include <asm/io.h> + +/*---------------------------------------------------------------------*/ +#undef DEBUG_FLASH + +#ifdef DEBUG_FLASH +#define DEBUGF(fmt,args...) printf(fmt ,##args) +#else +#define DEBUGF(fmt,args...) +#endif +/*---------------------------------------------------------------------*/ + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + +static ulong flash_get_size (ulong addr, flash_info_t *info); +static int flash_get_offsets (ulong base, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); +static void flash_reset (ulong addr); + +unsigned long flash_init (void) +{ + unsigned int i; + unsigned long flash_size = 0; + + /* 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 = 0; + flash_info[i].size = 0; + } + + DEBUGF("\n## Get flash size @ 0x%08x\n", CFG_FLASH_BASE); + + flash_size = flash_get_size (CFG_FLASH_BASE, flash_info); + + DEBUGF("## Flash bank size: %08lx\n", flash_size); + + if (flash_size) { +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE && \ + CFG_MONITOR_BASE < CFG_FLASH_BASE + CFG_FLASH_MAX_SIZE + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + monitor_flash_len - 1, + &flash_info[0]); +#endif + +#ifdef CFG_ENV_IS_IN_FLASH + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, + &flash_info[0]); +#endif + + } else { + puts ("Warning: the BOOT Flash is not initialised !"); + } + + return flash_size; +} + +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (ulong addr, flash_info_t *info) +{ + short i; + uchar value; + + /* Write auto select command: read Manufacturer ID */ + out8(addr + 0x0555, 0xAA); + iobarrier_rw(); + out8(addr + 0x02AA, 0x55); + iobarrier_rw(); + out8(addr + 0x0555, 0x90); + iobarrier_rw(); + + value = in8(addr); + iobarrier_rw(); + + DEBUGF("Manuf. ID @ 0x%08lx: 0x%08x\n", (ulong)addr, value); + + switch (value | (value << 16)) { + case AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + + case FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + + case STM_MANUFACT: + info->flash_id = FLASH_MAN_STM; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + flash_reset (addr); + return 0; + } + + value = in8(addr + 1); /* device ID */ + iobarrier_rw(); + + DEBUGF("Device ID @ 0x%08lx: 0x%08x\n", addr+1, value); + + switch ((ulong)value) { + case AMD_ID_F040B: + DEBUGF("Am29F040B\n"); + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x00080000; + break; /* => 512 kB */ + + case AMD_ID_LV040B: + DEBUGF("Am29LV040B\n"); + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x00080000; + break; /* => 512 kB */ + + case AMD_ID_LV400T: + DEBUGF("Am29LV400T\n"); + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00100000; + break; /* => 1 MB */ + + case AMD_ID_LV400B: + DEBUGF("Am29LV400B\n"); + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00100000; + break; /* => 1 MB */ + + case AMD_ID_LV800T: + DEBUGF("Am29LV800T\n"); + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00200000; + break; /* => 2 MB */ + + case AMD_ID_LV800B: + DEBUGF("Am29LV400B\n"); + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00200000; + break; /* => 2 MB */ + + case AMD_ID_LV160T: + DEBUGF("Am29LV160T\n"); + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00400000; + break; /* => 4 MB */ + + case AMD_ID_LV160B: + DEBUGF("Am29LV160B\n"); + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00400000; + break; /* => 4 MB */ + + case AMD_ID_LV320T: + DEBUGF("Am29LV320T\n"); + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ + +#if 0 + /* Has the same ID as AMD_ID_LV320T, to be fixed */ + case AMD_ID_LV320B: + DEBUGF("Am29LV320B\n"); + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ +#endif + + case AMD_ID_LV033C: + DEBUGF("Am29LV033C\n"); + info->flash_id += FLASH_AM033C; + info->sector_count = 64; + info->size = 0x01000000; + break; /* => 16Mb */ + + case STM_ID_F040B: + DEBUGF("M29F040B\n"); + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x00080000; + break; /* => 512 kB */ + + default: + info->flash_id = FLASH_UNKNOWN; + flash_reset (addr); + return (0); /* => no or unknown flash */ + + } + + if (info->sector_count > CFG_MAX_FLASH_SECT) { + printf ("** ERROR: sector count %d > max (%d) **\n", + info->sector_count, CFG_MAX_FLASH_SECT); + info->sector_count = CFG_MAX_FLASH_SECT; + } + + if (! flash_get_offsets (addr, info)) { + flash_reset (addr); + return 0; + } + + /* 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 */ + value = in8(info->start[i] + 2); + iobarrier_rw(); + info->protect[i] = (value & 1) != 0; + } + + /* + * Reset bank to read mode + */ + flash_reset (addr); + + return (info->size); +} + +static int flash_get_offsets (ulong base, flash_info_t *info) +{ + unsigned int i; + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: + /* set sector offsets for uniform sector type */ + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base + i * info->size / + info->sector_count; + } + break; + default: + return 0; + } + + return 1; +} + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + volatile ulong addr = info->start[0]; + int flag, prot, sect, l_sect; + ulong start, now, last; + + 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 %08lx - aborted\n", + info->flash_id); + 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(); + + out8(addr + 0x555, 0xAA); + iobarrier_rw(); + out8(addr + 0x2AA, 0x55); + iobarrier_rw(); + out8(addr + 0x555, 0x80); + iobarrier_rw(); + out8(addr + 0x555, 0xAA); + iobarrier_rw(); + out8(addr + 0x2AA, 0x55); + iobarrier_rw(); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = info->start[sect]; + out8(addr, 0x30); + iobarrier_rw(); + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer (0); + last = start; + addr = info->start[l_sect]; + + DEBUGF ("Start erase timeout: %d\n", CFG_FLASH_ERASE_TOUT); + + while ((in8(addr) & 0x80) != 0x80) { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + flash_reset (info->start[0]); + return 1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + iobarrier_rw(); + } + +DONE: + /* reset to read mode */ + flash_reset (info->start[0]); + + 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)); +} + +/* + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + volatile ulong addr = info->start[0]; + ulong start; + int i; + + /* Check if Flash is (sufficiently) erased */ + if ((in32(dest) & data) != data) { + return (2); + } + + /* write each byte out */ + for (i = 0; i < 4; i++) { + char *data_ch = (char *)&data; + int flag = disable_interrupts(); + + out8(addr + 0x555, 0xAA); + iobarrier_rw(); + out8(addr + 0x2AA, 0x55); + iobarrier_rw(); + out8(addr + 0x555, 0xA0); + iobarrier_rw(); + out8(dest+i, data_ch[i]); + iobarrier_rw(); + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + while ((in8(dest+i) & 0x80) != (data_ch[i] & 0x80)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + flash_reset (addr); + return (1); + } + iobarrier_rw(); + } + } + + flash_reset (addr); + return (0); +} + +/* + * Reset bank to read mode + */ +static void flash_reset (ulong addr) +{ + out8(addr, 0xF0); /* reset bank */ + iobarrier_rw(); +} + +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 & FLASH_VENDMASK) { + case FLASH_MAN_AMD: printf ("AMD "); break; + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; + case FLASH_MAN_BM: printf ("BRIGHT MICRO "); break; + case FLASH_MAN_STM: printf ("SGS THOMSON "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: printf ("29F040 or 29LV040 (4 Mbit, uniform sectors)\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_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; + default: printf ("Unknown Chip Type\n"); + break; + } + + if (info->size % 0x100000 == 0) { + printf (" Size: %ld MB in %d Sectors\n", + info->size / 0x100000, info->sector_count); + } else if (info->size % 0x400 == 0) { + printf (" Size: %ld KB in %d Sectors\n", + info->size / 0x400, info->sector_count); + } else { + printf (" Size: %ld B in %d Sectors\n", + info->size, 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"); +} diff --git a/board/pcippc2/fpga_serial.c b/board/pcippc2/fpga_serial.c new file mode 100755 index 0000000..579bfc7 --- /dev/null +++ b/board/pcippc2/fpga_serial.c @@ -0,0 +1,132 @@ +/* + * (C) Copyright 2002 + * 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> +#include <common.h> +#include <asm/io.h> + +#include "fpga_serial.h" +#include "hardware.h" +#include "pcippc2.h" + + /* 8 data, 1 stop, no parity + */ +#define LCRVAL 0x03 + /* RTS/DTR + */ +#define MCRVAL 0x03 + /* Clear & enable FIFOs + */ +#define FCRVAL 0x07 + +static void fpga_serial_wait (void); +static void fpga_serial_print (char c); + +void fpga_serial_init (int baudrate) +{ + int clock_divisor = 115200 / baudrate; + + out8 (FPGA (INT, SERIAL_CONFIG), 0x24); + iobarrier_rw (); + + fpga_serial_wait (); + + out8 (UART (IER), 0); + out8 (UART (LCR), LCRVAL | 0x80); + iobarrier_rw (); + out8 (UART (DLL), clock_divisor & 0xff); + out8 (UART (DLM), clock_divisor >> 8); + iobarrier_rw (); + out8 (UART (LCR), LCRVAL); + iobarrier_rw (); + out8 (UART (MCR), MCRVAL); + out8 (UART (FCR), FCRVAL); + iobarrier_rw (); +} + +void fpga_serial_putc (char c) +{ + if (c) { + fpga_serial_print (c); + } +} + +void fpga_serial_puts (const char *s) +{ + while (*s) { + fpga_serial_print (*s++); + } +} + +int fpga_serial_getc (void) +{ + while ((in8 (UART (LSR)) & 0x01) == 0); + + return in8 (UART (RBR)); +} + +int fpga_serial_tstc (void) +{ + return (in8 (UART (LSR)) & 0x01) != 0; +} + +void fpga_serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int clock_divisor = 115200 / gd->baudrate; + + fpga_serial_wait (); + + out8 (UART (LCR), LCRVAL | 0x80); + iobarrier_rw (); + out8 (UART (DLL), clock_divisor & 0xff); + out8 (UART (DLM), clock_divisor >> 8); + iobarrier_rw (); + out8 (UART (LCR), LCRVAL); + iobarrier_rw (); +} + +static void fpga_serial_wait (void) +{ + while ((in8 (UART (LSR)) & 0x40) == 0); +} + +static void fpga_serial_print (char c) +{ + if (c == '\n') { + while ((in8 (UART (LSR)) & 0x20) == 0); + + out8 (UART (THR), '\r'); + iobarrier_rw (); + } + + while ((in8 (UART (LSR)) & 0x20) == 0); + + out8 (UART (THR), c); + iobarrier_rw (); + + if (c == '\n') { + fpga_serial_wait (); + } +} diff --git a/board/pcippc2/fpga_serial.h b/board/pcippc2/fpga_serial.h new file mode 100755 index 0000000..92c9cdd --- /dev/null +++ b/board/pcippc2/fpga_serial.h @@ -0,0 +1,34 @@ +/* + * (C) Copyright 2002 + * 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 _FPGA_SERIAL_H_ +#define _FPGA_SERIAL_H_ + +extern void fpga_serial_init (int); +extern void fpga_serial_putc (char); +extern void fpga_serial_puts (const char *); +extern int fpga_serial_getc (void); +extern int fpga_serial_tstc (void); +extern void fpga_serial_setbrg (void); + +#endif diff --git a/board/pcippc2/hardware.h b/board/pcippc2/hardware.h new file mode 100755 index 0000000..489929d --- /dev/null +++ b/board/pcippc2/hardware.h @@ -0,0 +1,48 @@ +/* + * (C) Copyright 2002 + * 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 _HARDWARE_H_ +#define _HARDWARE_H_ + +#include "cpc710.h" +#include "cpc710_pci.h" +#include "pcippc2_fpga.h" +#include "ns16550.h" + +#define REG(r, x) (HW_PHYS_##r + HW_##r##_##x) + + /* Address map: + * + * 0x00000000-0x20000000 SDRAM + * 0x40000000-0x00008000 Init RAM in the CPU DCache + * 0xf0000000-0xf8000000 CPCI MEM + * 0xf8000000-0xfc000000 Local PCI MEM + * 0xfc000000-0xfe000000 CPCI I/O + * 0xfe000000-0xff000000 Local PCI I/O + * 0xff000000-0xff201000 System configuration space + * 0xff400000-0xff500000 Local PCI bridge space + * 0xff500000-0xff600000 CPCI bridge space + * 0xfff00000-0xfff80000 Boot Flash + */ + +#endif diff --git a/board/pcippc2/i2c.c b/board/pcippc2/i2c.c new file mode 100755 index 0000000..36b1d0f --- /dev/null +++ b/board/pcippc2/i2c.c @@ -0,0 +1,257 @@ +/* + * (C) Copyright 2002 + * 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> +#include <common.h> +#include <asm/io.h> + +#include "hardware.h" +#include "i2c.h" + +static void i2c_start (void); +static void i2c_stop (void); +static int i2c_write (u8 data); +static void i2c_read (u8 * data); + +static inline void i2c_port_start (void); +static inline void i2c_clock (unsigned int val); +static inline void i2c_data (unsigned int val); +static inline unsigned int + i2c_in (void); +static inline void i2c_write_bit (unsigned int val); +static inline unsigned int + i2c_read_bit (void); + +static inline void i2c_udelay (unsigned int time); + +int i2c_read_byte ( + u8 * data, + u8 dev, + u8 offset) +{ + int err = 0; + + i2c_start(); + + err = ! i2c_write(dev); + + if (! err) + { + err = ! i2c_write(offset); + } + + if (! err) + { + i2c_start(); + } + + if (! err) + { + err = ! i2c_write(dev | 0x01); + } + + if (! err) + { + i2c_read(data); + } + + i2c_stop(); + + return ! err; +} + +static inline void i2c_udelay ( + unsigned int time) +{ + int v; + + asm volatile("mtdec %0" : : "r" (time * ((CFG_BUS_CLK / 4) / 1000000))); + + do + { + asm volatile("isync; mfdec %0" : "=r" (v)); + } while (v >= 0); +} + + /* Low-level hardware access + */ + +#define BIT_GPDATA 0x80000000 +#define BIT_GPCLK 0x40000000 + +static inline void i2c_port_start (void) +{ + out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~(BIT_GPCLK | BIT_GPDATA)); + out32(REG(CPC0, GPOUT), in32(REG(CPC0, GPOUT)) & ~(BIT_GPCLK | BIT_GPDATA)); + iobarrier_rw(); + + i2c_udelay(1); +} + +static inline void i2c_clock ( + unsigned int val) +{ + if (val) + { + out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~BIT_GPCLK); + } + else + { + out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) | BIT_GPCLK); + } + + iobarrier_rw(); + + i2c_udelay(1); +} + +static inline void i2c_data ( + unsigned int val) +{ + if (val) + { + out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~BIT_GPDATA); + } + else + { + out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) | BIT_GPDATA); + } + + iobarrier_rw(); + + i2c_udelay(1); +} + +static inline unsigned int i2c_in (void) +{ + unsigned int val = ((in32(REG(CPC0, GPIN)) & BIT_GPDATA) != 0)?1:0; + + iobarrier_rw(); + + return val; +} + + + /* Protocol implementation + */ + +static inline void i2c_write_bit ( + unsigned int val) +{ + i2c_data(val); + i2c_udelay(10); + i2c_clock(1); + i2c_udelay(10); + i2c_clock(0); + i2c_udelay(10); +} + +static inline unsigned int i2c_read_bit (void) +{ + unsigned int val; + + i2c_data(1); + i2c_udelay(10); + + i2c_clock(1); + i2c_udelay(10); + + val = i2c_in(); + + i2c_clock(0); + i2c_udelay(10); + + return val; +} + +unsigned int i2c_reset (void) +{ + unsigned int val; + int i; + + i2c_port_start(); + + i=0; + do { + i2c_udelay(10); + i2c_clock(0); + i2c_udelay(10); + i2c_clock(1); + i2c_udelay(10); + val = i2c_in(); + i++; + } while ((i<9)&&(val==0)); + return (val); +} + + +static void i2c_start (void) +{ + i2c_data(1); + i2c_clock(1); + i2c_udelay(10); + i2c_data(0); + i2c_udelay(10); + i2c_clock(0); + i2c_udelay(10); +} + +static void i2c_stop (void) +{ + i2c_data(0); + i2c_udelay(10); + i2c_clock(1); + i2c_udelay(10); + i2c_data(1); + i2c_udelay(10); +} + +static int i2c_write ( + u8 data) +{ + unsigned int i; + + for (i = 0; i < 8; i++) + { + i2c_write_bit(data >> 7); + data <<= 1; + } + + return i2c_read_bit() == 0; +} + +static void i2c_read ( + u8 * data) +{ + unsigned int i; + u8 val = 0; + + for (i = 0; i < 8; i++) + { + val <<= 1; + val |= i2c_read_bit(); + } + + *data = val; + i2c_write_bit(1); /* NoAck */ +} diff --git a/board/pcippc2/i2c.h b/board/pcippc2/i2c.h new file mode 100755 index 0000000..1224b42 --- /dev/null +++ b/board/pcippc2/i2c.h @@ -0,0 +1,36 @@ +/* + * (C) Copyright 2002 + * 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 _I2C_H_ +#define _I2C_H_ + +#include <common.h> + +extern int i2c_read_byte (u8 * data, + u8 dev, + u8 offset); + +extern unsigned int i2c_reset (void); + + +#endif diff --git a/board/pcippc2/ns16550.h b/board/pcippc2/ns16550.h new file mode 100755 index 0000000..7023f13 --- /dev/null +++ b/board/pcippc2/ns16550.h @@ -0,0 +1,41 @@ +/* + * (C) Copyright 2002 + * 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 _NS16550_H_ +#define _NS16550_H_ + +#define NS16550_RBR 0x00 +#define NS16550_IER 0x01 +#define NS16550_FCR 0x02 +#define NS16550_LCR 0x03 +#define NS16550_MCR 0x04 +#define NS16550_LSR 0x05 +#define NS16550_MSR 0x06 +#define NS16550_SCR 0x07 + +#define NS16550_THR NS16550_RBR +#define NS16550_IIR NS16550_FCR +#define NS16550_DLL NS16550_RBR +#define NS16550_DLM NS16550_IER + +#endif diff --git a/board/pcippc2/pcippc2.c b/board/pcippc2/pcippc2.c new file mode 100755 index 0000000..231b505 --- /dev/null +++ b/board/pcippc2/pcippc2.c @@ -0,0 +1,245 @@ +/* + * (C) Copyright 2002 + * 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> +#include <common.h> +#include <command.h> +#include <asm/io.h> +#include <linux/mtd/doc2000.h> +#include <watchdog.h> +#include <pci.h> + +#include "hardware.h" +#include "pcippc2.h" +#include "sconsole.h" +#include "fpga_serial.h" + +#if defined(CONFIG_WATCHDOG) + +static int pcippc2_wdt_init_done = 0; + +void pcippc2_wdt_init (void); + +#endif + + /* Check board identity + */ +int checkboard (void) +{ +#ifdef CONFIG_PCIPPC2 + puts ("Board: Gespac PCIPPC-2\n"); +#else + puts ("Board: Gespac PCIPPC-6\n"); +#endif + return 0; +} + + /* RAM size is stored in CPC0_RGBAN1 + */ +u32 pcippc2_sdram_size (void) +{ + return in32 (REG (CPC0, RGBAN1)); +} + +long initdram (int board_type) +{ + return cpc710_ram_init (); +} + +int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + out32 (REG (CPC0, SPOR), 0); + iobarrier_rw (); + while (1); + /* notreached */ + return (-1); +} + +int board_early_init_f (void) +{ + out32 (REG (CPC0, RSTR), 0xC0000000); + iobarrier_rw (); + + out32 (REG (CPC0, RSTR), 0xF0000000); + iobarrier_rw (); + + out32 (REG (CPC0, UCTL), 0x00F80000); + + out32 (REG (CPC0, SIOC0), 0x30000000); + + out32 (REG (CPC0, ABCNTL), 0x00000000); + + out32 (REG (CPC0, SESR), 0x00000000); + out32 (REG (CPC0, SEAR), 0x00000000); + + /* Detect IBM Avignon CPC710 Revision */ + if ((in32 (REG (CPC0, UCTL)) & 0x000000F0) == CPC710_TYPE_100P) + out32 (REG (CPC0, PGCHP), 0xA0000040); + else + out32 (REG (CPC0, PGCHP), 0x80800040); + + + out32 (REG (CPC0, ATAS), 0x709C2508); + + iobarrier_rw (); + + return 0; +} + +void after_reloc (ulong dest_addr) +{ + DECLARE_GLOBAL_DATA_PTR; + + /* Jump to the main U-Boot board init code + */ + board_init_r ((gd_t *)gd, dest_addr); +} + +int misc_init_r (void) +{ + pcippc2_fpga_init (); + + pcippc2_cpci3264_init (); + +#if defined(CONFIG_WATCHDOG) + pcippc2_wdt_init (); +#endif + + fpga_serial_init (sconsole_get_baudrate ()); + + sconsole_putc = fpga_serial_putc; + sconsole_puts = fpga_serial_puts; + sconsole_getc = fpga_serial_getc; + sconsole_tstc = fpga_serial_tstc; + sconsole_setbrg = fpga_serial_setbrg; + + sconsole_flush (); + return (0); +} + +void pci_init_board (void) +{ + cpc710_pci_init (); + + /* FPGA requires no retry timeouts to be enabled + */ + cpc710_pci_enable_timeout (); +} + +void doc_init (void) +{ + doc_probe (pcippc2_fpga1_phys + HW_FPGA1_DOC); +} + +void pcippc2_cpci3264_init (void) +{ + pci_dev_t bdf = pci_find_device(FPGA_VENDOR_ID, FPGA_DEVICE_ID, 0); + + if (bdf == -1) + { + puts("Unable to find FPGA !\n"); + hang(); + } + + if((in32(pcippc2_fpga0_phys + HW_FPGA0_BOARD) & 0x01000000) == 0x01000000) + /* 32-bits Compact PCI bus - LSB bit */ + { + iobarrier_rw(); + out32(BRIDGE(CPCI, PCIDG), 0x40000000); /* 32-bits bridge, Pipeline */ + iobarrier_rw(); + } +} + +#if defined(CONFIG_WATCHDOG) + +void pcippc2_wdt_init (void) +{ + out16r (FPGA (WDT, PROG), 0xffff); + out8 (FPGA (WDT, CTRL), 0x1); + + pcippc2_wdt_init_done = 1; +} + +void pcippc2_wdt_done (void) +{ + out8 (FPGA (WDT, CTRL), 0x0); + + pcippc2_wdt_init_done = 0; +} + +void pcippc2_wdt_reset (void) +{ + if (pcippc2_wdt_init_done == 1) + out8 (FPGA (WDT, REFRESH), 0x56); +} + +void watchdog_reset (void) +{ + int re_enable = disable_interrupts (); + + pcippc2_wdt_reset (); + if (re_enable) + enable_interrupts (); +} + +#if (CONFIG_COMMANDS & CFG_CMD_BSP) +int do_wd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + switch (argc) { + case 1: + printf ("Watchdog timer status is %s\n", + pcippc2_wdt_init_done == 1 ? "on" : "off"); + + return 0; + case 2: + if (!strcmp(argv[1],"on")) { + pcippc2_wdt_init(); + printf("Watchdog timer now is on\n"); + + return 0; + + } else if (!strcmp(argv[1],"off")) { + pcippc2_wdt_done(); + printf("Watchdog timer now is off\n"); + + return 0; + + } else + break; + default: + break; + } + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +U_BOOT_CMD( + wd, 2, 1, do_wd, + "wd - check and set watchdog\n", + "on - switch watchDog on\n" + "wd off - switch watchdog off\n" + "wd - print current status\n" +); + +#endif /* CFG_CMD_BSP */ +#endif /* CONFIG_WATCHDOG */ diff --git a/board/pcippc2/pcippc2.h b/board/pcippc2/pcippc2.h new file mode 100755 index 0000000..3820bbe --- /dev/null +++ b/board/pcippc2/pcippc2.h @@ -0,0 +1,51 @@ +/* + * (C) Copyright 2002 + * 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 _PCIPPC2_H_ +#define _PCIPPC2_H_ + +#include <config.h> +#include <common.h> + +#include "hardware.h" + +#define FPGA(r, p) (pcippc2_fpga0_phys + HW_FPGA0_##r##_##p) +#define UART(r) (pcippc2_fpga0_phys + HW_FPGA0_UART1 + NS16550_##r * 4) +#define RTC(r) (pcippc2_fpga1_phys + HW_FPGA1_RTC + r) + +extern u32 pcippc2_fpga0_phys; +extern u32 pcippc2_fpga1_phys; + +extern u32 pcippc2_sdram_size (void); + +extern void pcippc2_fpga_init (void); + +extern void pcippc2_cpci3264_init (void); + +extern void cpc710_pci_init (void); +extern void cpc710_pci_enable_timeout (void); + +extern unsigned long + cpc710_ram_init (void); + +#endif diff --git a/board/pcippc2/pcippc2_fpga.c b/board/pcippc2/pcippc2_fpga.c new file mode 100755 index 0000000..7f6739d --- /dev/null +++ b/board/pcippc2/pcippc2_fpga.c @@ -0,0 +1,87 @@ +/* + * (C) Copyright 2002 + * 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> +#include <common.h> +#include <asm/io.h> + +#include "pci.h" + +#include "hardware.h" +#include "pcippc2.h" + +u32 pcippc2_fpga0_phys; +u32 pcippc2_fpga1_phys; + +void pcippc2_fpga_init (void) +{ + pci_dev_t bdf = pci_find_device(FPGA_VENDOR_ID, FPGA_DEVICE_ID, 0); + unsigned int addr; + u16 cmd; + + if (bdf == -1) + { + puts("Unable to find FPGA !\n"); + hang(); + } + + pci_read_config_word(bdf, PCI_COMMAND, &cmd); + if ((cmd & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)) != (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)) + { + puts("FPGA is not configured !\n"); + hang(); + } + + pci_read_config_dword(bdf, PCI_BASE_ADDRESS_0, &addr); + if (addr & 0x1) + { + /* IO space + */ + pcippc2_fpga0_phys = pci_io_to_phys(bdf, addr & 0xfffffffc); + } + else + { + /* Memory space + */ + pcippc2_fpga0_phys = pci_mem_to_phys(bdf, addr & 0xfffffff0); + } + + pci_read_config_dword(bdf, PCI_BASE_ADDRESS_1, &addr); + if (addr & 0x1) + { + /* IO space + */ + pcippc2_fpga1_phys = pci_io_to_phys(bdf, addr & 0xfffffffc); + } + else + { + /* Memory space + */ + pcippc2_fpga1_phys = pci_mem_to_phys(bdf, addr & 0xfffffff0); + } + + /* Interrupts are not used + */ + out32(FPGA(INT, INTR_MASK), 0xffffffff); + iobarrier_rw(); +} diff --git a/board/pcippc2/pcippc2_fpga.h b/board/pcippc2/pcippc2_fpga.h new file mode 100755 index 0000000..850c331 --- /dev/null +++ b/board/pcippc2/pcippc2_fpga.h @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2002 + * 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 _PCIPPC2_FPGA_H_ +#define _PCIPPC2_FPGA_H_ + +#define FPGA_VENDOR_ID 0x1310 +#define FPGA_DEVICE_ID 0x000d + +#define HW_FPGA0_INT 0x0000 +#define HW_FPGA0_BOARD 0x0060 +#define HW_FPGA0_UART1 0x0080 +#define HW_FPGA0_UART2 0x0100 +#define HW_FPGA0_RTC 0x2000 +#define HW_FPGA0_DOC 0x4000 +#define HW_FPGA1_RTC 0x0000 +#define HW_FPGA1_DOC 0x4000 + +#define HW_FPGA0_INT_INTR_MASK 0x30 +#define HW_FPGA0_INT_INTR_STATUS 0x34 +#define HW_FPGA0_INT_INTR_EOI 0x40 +#define HW_FPGA0_INT_SERIAL_CONFIG 0x5c + +#define HW_FPGA0_WDT_CTRL 0x44 +#define HW_FPGA0_WDT_PROG 0x48 +#define HW_FPGA0_WDT_VAL 0x4c +#define HW_FPGA0_WDT_REFRESH 0x50 + +#endif diff --git a/board/pcippc2/sconsole.c b/board/pcippc2/sconsole.c new file mode 100755 index 0000000..a9f2b29 --- /dev/null +++ b/board/pcippc2/sconsole.c @@ -0,0 +1,141 @@ +/* + * (C) Copyright 2002 + * 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> +#include <common.h> + +#include "sconsole.h" + +void (*sconsole_putc) (char) = 0; +void (*sconsole_puts) (const char *) = 0; +int (*sconsole_getc) (void) = 0; +int (*sconsole_tstc) (void) = 0; +void (*sconsole_setbrg) (void) = 0; + +int serial_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + sconsole_buffer_t *sb = SCONSOLE_BUFFER; + + sb->pos = 0; + sb->size = 0; + sb->baud = gd->baudrate; + sb->max_size = CFG_SCONSOLE_SIZE - sizeof (sconsole_buffer_t); + + return (0); +} + +void serial_putc (char c) +{ + if (sconsole_putc) { + (*sconsole_putc) (c); + } else { + sconsole_buffer_t *sb = SCONSOLE_BUFFER; + + if (c) { + sb->data[sb->pos++] = c; + if (sb->pos == sb->max_size) { + sb->pos = 0; + } + if (sb->size < sb->max_size) { + sb->size++; + } + } + } +} + +void serial_puts (const char *s) +{ + if (sconsole_puts) { + (*sconsole_puts) (s); + } else { + sconsole_buffer_t *sb = SCONSOLE_BUFFER; + + while (*s) { + sb->data[sb->pos++] = *s++; + if (sb->pos == sb->max_size) { + sb->pos = 0; + } + if (sb->size < sb->max_size) { + sb->size++; + } + } + } +} + +int serial_getc (void) +{ + if (sconsole_getc) { + return (*sconsole_getc) (); + } else { + return 0; + } +} + +int serial_tstc (void) +{ + if (sconsole_tstc) { + return (*sconsole_tstc) (); + } else { + return 0; + } +} + +void serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + if (sconsole_setbrg) { + (*sconsole_setbrg) (); + } else { + sconsole_buffer_t *sb = SCONSOLE_BUFFER; + + sb->baud = gd->baudrate; + } +} + +int sconsole_get_baudrate (void) +{ + sconsole_buffer_t *sb = SCONSOLE_BUFFER; + + return sb->baud; +} + +void sconsole_flush (void) +{ + if (sconsole_putc) { + sconsole_buffer_t *sb = SCONSOLE_BUFFER; + unsigned int end = sb->pos < sb->size + ? sb->pos + sb->max_size - sb->size + : sb->pos - sb->size; + + while (sb->size) { + (*sconsole_putc) (sb->data[end++]); + if (end == sb->max_size) { + end = 0; + } + sb->size--; + } + } +} diff --git a/board/pcippc2/sconsole.h b/board/pcippc2/sconsole.h new file mode 100755 index 0000000..40fd75b --- /dev/null +++ b/board/pcippc2/sconsole.h @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2002 + * 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 _SCONSOLE_H_ +#define _SCONSOLE_H_ + +#include <config.h> + +typedef struct sconsole_buffer_s +{ + unsigned long size; + unsigned long max_size; + unsigned long pos; + unsigned long baud; + char data [1]; +} sconsole_buffer_t; + +#define SCONSOLE_BUFFER ((sconsole_buffer_t *) CFG_SCONSOLE_ADDR) + +extern void (* sconsole_putc) (char); +extern void (* sconsole_puts) (const char *); +extern int (* sconsole_getc) (void); +extern int (* sconsole_tstc) (void); +extern void (* sconsole_setbrg) (void); + +extern void sconsole_flush (void); +extern int sconsole_get_baudrate (void); + +#endif diff --git a/board/pcippc2/u-boot.lds b/board/pcippc2/u-boot.lds new file mode 100755 index 0000000..5c8cd5a --- /dev/null +++ b/board/pcippc2/u-boot.lds @@ -0,0 +1,141 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * (C) Copyright 2002 + * 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 + */ + +/* + * 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 = .); +} |