summaryrefslogtreecommitdiff
path: root/board/pcippc2
diff options
context:
space:
mode:
authorwdenk <wdenk>2002-11-03 00:24:07 +0000
committerwdenk <wdenk>2002-11-03 00:24:07 +0000
commitc609719b8d1b2dca590e0ed499016d041203e403 (patch)
tree7ea1755d80903ff972f312a249eb856061d40e15 /board/pcippc2
parent5b1d713721c3ea02549940133f09236783dda1f9 (diff)
Initial revision
Diffstat (limited to 'board/pcippc2')
-rw-r--r--board/pcippc2/cpc710_init_ram.c254
-rw-r--r--board/pcippc2/cpc710_pci.c309
-rw-r--r--board/pcippc2/i2c.c257
-rw-r--r--board/pcippc2/pcippc2.c214
4 files changed, 1034 insertions, 0 deletions
diff --git a/board/pcippc2/cpc710_init_ram.c b/board/pcippc2/cpc710_init_ram.c
new file mode 100644
index 0000000000..57ed8f087f
--- /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 100644
index 0000000000..9975cdaa58
--- /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/i2c.c b/board/pcippc2/i2c.c
new file mode 100644
index 0000000000..36b1d0f44d
--- /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/pcippc2.c b/board/pcippc2/pcippc2.c
new file mode 100644
index 0000000000..e1b065b0ce
--- /dev/null
+++ b/board/pcippc2/pcippc2.c
@@ -0,0 +1,214 @@
+/*
+ * (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 ();
+}
+
+void do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+ out32 (REG (CPC0, SPOR), 0);
+ iobarrier_rw ();
+ while (1);
+}
+
+int board_pre_init (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, dest_addr);
+}
+
+int misc_init_r (void)
+{
+ pcippc2_fpga_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 (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);
+}
+
+#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, bd_t *bd, 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;
+}
+
+#endif /* CFG_CMD_BSP */
+#endif /* CONFIG_WATCHDOG */