summaryrefslogtreecommitdiffstats
path: root/qemu/roms/u-boot/board/atc
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/u-boot/board/atc')
-rw-r--r--qemu/roms/u-boot/board/atc/Makefile8
-rw-r--r--qemu/roms/u-boot/board/atc/atc.c382
-rw-r--r--qemu/roms/u-boot/board/atc/flash.c647
-rw-r--r--qemu/roms/u-boot/board/atc/ti113x.c620
4 files changed, 1657 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/board/atc/Makefile b/qemu/roms/u-boot/board/atc/Makefile
new file mode 100644
index 000000000..3a163c4c6
--- /dev/null
+++ b/qemu/roms/u-boot/board/atc/Makefile
@@ -0,0 +1,8 @@
+#
+# (C) Copyright 2001-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y = atc.o flash.o ti113x.o
diff --git a/qemu/roms/u-boot/board/atc/atc.c b/qemu/roms/u-boot/board/atc/atc.c
new file mode 100644
index 000000000..0038561b1
--- /dev/null
+++ b/qemu/roms/u-boot/board/atc/atc.c
@@ -0,0 +1,382 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <ioports.h>
+#include <mpc8260.h>
+#include <pci.h>
+
+/*
+ * I/O Port configuration table
+ *
+ * if conf is 1, then that port pin will be configured at boot time
+ * according to the five values podr/pdir/ppar/psor/pdat for that entry
+ */
+
+const iop_conf_t iop_conf_tab[4][32] = {
+
+ /* Port A configuration */
+ { /* conf ppar psor pdir podr pdat */
+ /* PA31 */ { 1, 1, 1, 0, 0, 0 }, /* FCC1 MII COL */
+ /* PA30 */ { 1, 1, 1, 0, 0, 0 }, /* FCC1 MII CRS */
+ /* PA29 */ { 1, 1, 1, 1, 0, 0 }, /* FCC1 MII TX_ER */
+ /* PA28 */ { 1, 1, 1, 1, 0, 0 }, /* FCC1 MII TX_EN */
+ /* PA27 */ { 1, 1, 1, 0, 0, 0 }, /* FCC1 MII RX_DV */
+ /* PA26 */ { 1, 1, 1, 0, 0, 0 }, /* FCC1 MII RX_ER */
+ /* PA25 */ { 1, 0, 0, 1, 0, 0 }, /* FCC2 MII MDIO */
+ /* PA24 */ { 1, 0, 0, 1, 0, 0 }, /* FCC2 MII MDC */
+ /* PA23 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 MII MDIO */
+ /* PA22 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 MII MDC */
+ /* PA21 */ { 1, 1, 0, 1, 0, 0 }, /* FCC1 MII TxD[3] */
+ /* PA20 */ { 1, 1, 0, 1, 0, 0 }, /* FCC1 MII TxD[2] */
+ /* PA19 */ { 1, 1, 0, 1, 0, 0 }, /* FCC1 MII TxD[1] */
+ /* PA18 */ { 1, 1, 0, 1, 0, 0 }, /* FCC1 MII TxD[0] */
+ /* PA17 */ { 1, 1, 0, 0, 0, 0 }, /* FCC1 MII RxD[0] */
+ /* PA16 */ { 1, 1, 0, 0, 0, 0 }, /* FCC1 MII RxD[1] */
+ /* PA15 */ { 1, 1, 0, 0, 0, 0 }, /* FCC1 MII RxD[2] */
+ /* PA14 */ { 1, 1, 0, 0, 0, 0 }, /* FCC1 MII RxD[3] */
+ /* PA13 */ { 1, 0, 0, 1, 0, 0 }, /* FCC2 MII TXSL1 */
+ /* PA12 */ { 1, 0, 0, 1, 0, 1 }, /* FCC2 MII TXSL0 */
+ /* PA11 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 MII TXSL1 */
+ /* PA10 */ { 1, 0, 0, 1, 0, 1 }, /* FCC1 MII TXSL0 */
+#if 1
+ /* PA9 */ { 0, 1, 0, 1, 0, 0 }, /* SMC2 TXD */
+ /* PA8 */ { 0, 1, 0, 0, 0, 0 }, /* SMC2 RXD */
+#else
+ /* PA9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC2 TXD */
+ /* PA8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC2 RXD */
+#endif
+ /* PA7 */ { 0, 0, 0, 0, 0, 0 }, /* PA7 */
+ /* PA6 */ { 1, 0, 0, 1, 0, 1 }, /* FCC2 MII PAUSE */
+ /* PA5 */ { 1, 0, 0, 1, 0, 1 }, /* FCC1 MII PAUSE */
+ /* PA4 */ { 1, 0, 0, 1, 0, 0 }, /* FCC2 MII PWRDN */
+ /* PA3 */ { 1, 0, 0, 1, 0, 0 }, /* FCC1 MII PWRDN */
+ /* PA2 */ { 0, 0, 0, 0, 0, 0 }, /* PA2 */
+ /* PA1 */ { 1, 0, 0, 0, 0, 0 }, /* FCC2 MII MDINT */
+ /* PA0 */ { 1, 0, 0, 1, 0, 0 } /* FCC1 MII MDINT */
+ },
+
+ /* Port B configuration */
+ { /* conf ppar psor pdir podr pdat */
+ /* PB31 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TX_ER */
+ /* PB30 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_DV */
+ /* PB29 */ { 1, 1, 1, 1, 0, 0 }, /* FCC2 MII TX_EN */
+ /* PB28 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_ER */
+ /* PB27 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII COL */
+ /* PB26 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII CRS */
+ /* PB25 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[3] */
+ /* PB24 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[2] */
+ /* PB23 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[1] */
+ /* PB22 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[0] */
+ /* PB21 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[0] */
+ /* PB20 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[1] */
+ /* PB19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[2] */
+ /* PB18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[3] */
+ /* PB17 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RX_DV */
+ /* PB16 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RX_ER */
+ /* PB15 */ { 1, 1, 0, 1, 0, 0 }, /* FCC3 MII TX_ER */
+ /* PB14 */ { 1, 1, 0, 1, 0, 0 }, /* FCC3 MII TX_EN */
+ /* PB13 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII COL */
+ /* PB12 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII CRS */
+ /* PB11 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RxD */
+ /* PB10 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RxD */
+ /* PB9 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RxD */
+ /* PB8 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RxD */
+ /* PB7 */ { 1, 1, 0, 1, 0, 0 }, /* FCC3 MII TxD */
+ /* PB6 */ { 1, 1, 0, 1, 0, 0 }, /* FCC3 MII TxD */
+ /* PB5 */ { 1, 1, 0, 1, 0, 0 }, /* FCC3 MII TxD */
+ /* PB4 */ { 1, 1, 0, 1, 0, 0 }, /* FCC3 MII TxD */
+ /* PB3 */ { 0, 0, 0, 0, 0, 0 }, /* PB3 */
+ /* PB2 */ { 0, 0, 0, 0, 0, 0 }, /* PB2 */
+ /* PB1 */ { 0, 0, 0, 0, 0, 0 }, /* PB1 */
+ /* PB0 */ { 0, 0, 0, 0, 0, 0 } /* PB0 */
+ },
+
+ /* Port C */
+ { /* conf ppar psor pdir podr pdat */
+ /* PC31 */ { 0, 0, 0, 0, 0, 0 }, /* PC31 */
+ /* PC30 */ { 0, 0, 0, 0, 0, 0 }, /* PC30 */
+ /* PC29 */ { 1, 0, 0, 0, 0, 0 }, /* SCC1 CTS */
+ /* PC28 */ { 1, 0, 0, 0, 0, 0 }, /* SCC2 CTS */
+ /* PC27 */ { 0, 0, 0, 0, 0, 0 }, /* PC27 */
+ /* PC26 */ { 0, 0, 0, 0, 0, 0 }, /* PC26 */
+ /* PC25 */ { 0, 0, 0, 0, 0, 0 }, /* PC25 */
+ /* PC24 */ { 0, 0, 0, 0, 0, 0 }, /* PC24 */
+ /* PC23 */ { 0, 0, 0, 0, 0, 0 }, /* FDC37C78 DACFD */
+ /* PC22 */ { 0, 0, 0, 0, 0, 0 }, /* FDC37C78 DNFD */
+ /* PC21 */ { 1, 1, 0, 0, 0, 0 }, /* FCC1 MII RX_CLK */
+ /* PC20 */ { 1, 1, 0, 0, 0, 0 }, /* FCC1 MII TX_CLK */
+ /* PC19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_CLK */
+ /* PC18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII TX_CLK */
+ /* PC17 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII RX_CLK */
+ /* PC16 */ { 1, 1, 0, 0, 0, 0 }, /* FCC3 MII TX_CLK */
+#if 0
+ /* PC15 */ { 0, 0, 0, 0, 0, 0 }, /* PC15 */
+#else
+ /* PC15 */ { 1, 1, 0, 1, 0, 0 }, /* PC15 */
+#endif
+ /* PC14 */ { 0, 0, 0, 0, 0, 0 }, /* PC14 */
+ /* PC13 */ { 0, 0, 0, 0, 0, 0 }, /* PC13 */
+ /* PC12 */ { 0, 0, 0, 0, 0, 0 }, /* PC12 */
+ /* PC11 */ { 0, 0, 0, 0, 0, 0 }, /* PC11 */
+ /* PC10 */ { 0, 0, 0, 0, 0, 0 }, /* PC10 */
+ /* PC9 */ { 0, 0, 0, 0, 0, 0 }, /* FC9 */
+ /* PC8 */ { 0, 0, 0, 0, 0, 0 }, /* PC8 */
+ /* PC7 */ { 0, 0, 0, 0, 0, 0 }, /* PC7 */
+ /* PC6 */ { 0, 0, 0, 0, 0, 0 }, /* PC6 */
+ /* PC5 */ { 0, 0, 0, 0, 0, 0 }, /* PC5 */
+ /* PC4 */ { 0, 0, 0, 0, 0, 0 }, /* PC4 */
+ /* PC3 */ { 0, 0, 0, 0, 0, 0 }, /* PC3 */
+ /* PC2 */ { 0, 0, 0, 0, 0, 0 }, /* PC2 */
+ /* PC1 */ { 0, 0, 0, 0, 0, 0 }, /* PC1 */
+ /* PC0 */ { 0, 0, 0, 0, 0, 0 }, /* FDC37C78 DRQFD */
+ },
+
+ /* Port D */
+ { /* conf ppar psor pdir podr pdat */
+ /* PD31 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 RXD */
+ /* PD30 */ { 1, 1, 1, 1, 0, 0 }, /* SCC1 TXD */
+ /* PD29 */ { 1, 0, 0, 1, 0, 0 }, /* SCC1 RTS */
+ /* PD28 */ { 1, 1, 0, 0, 0, 0 }, /* SCC2 RXD */
+ /* PD27 */ { 1, 1, 0, 1, 0, 0 }, /* SCC2 TXD */
+ /* PD26 */ { 1, 0, 0, 1, 0, 0 }, /* SCC2 RTS */
+ /* PD25 */ { 0, 0, 0, 0, 0, 0 }, /* PD25 */
+ /* PD24 */ { 0, 0, 0, 0, 0, 0 }, /* PD24 */
+ /* PD23 */ { 0, 0, 0, 0, 0, 0 }, /* PD23 */
+ /* PD22 */ { 0, 0, 0, 0, 0, 0 }, /* PD22 */
+ /* PD21 */ { 0, 0, 0, 0, 0, 0 }, /* PD21 */
+ /* PD20 */ { 0, 0, 0, 0, 0, 0 }, /* PD20 */
+ /* PD19 */ { 0, 0, 0, 0, 0, 0 }, /* PD19 */
+ /* PD18 */ { 0, 0, 0, 0, 0, 0 }, /* PD18 */
+ /* PD17 */ { 0, 0, 0, 0, 0, 0 }, /* PD17 */
+ /* PD16 */ { 0, 0, 0, 0, 0, 0 }, /* PD16 */
+#if defined(CONFIG_SYS_I2C_SOFT)
+ /* PD15 */ { 1, 0, 0, 1, 1, 1 }, /* I2C SDA */
+ /* PD14 */ { 1, 0, 0, 1, 1, 1 }, /* I2C SCL */
+#else
+#if defined(CONFIG_HARD_I2C)
+ /* PD15 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SDA */
+ /* PD14 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SCL */
+#else /* normal I/O port pins */
+ /* PD15 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SDA */
+ /* PD14 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SCL */
+#endif
+#endif
+ /* PD13 */ { 0, 0, 0, 0, 0, 0 }, /* PD13 */
+ /* PD12 */ { 0, 0, 0, 0, 0, 0 }, /* PD12 */
+ /* PD11 */ { 0, 0, 0, 0, 0, 0 }, /* PD11 */
+ /* PD10 */ { 0, 0, 0, 0, 0, 0 }, /* PD10 */
+ /* PD9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC1 TXD */
+ /* PD8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC1 RXD */
+ /* PD7 */ { 0, 0, 0, 0, 0, 0 }, /* PD7 */
+ /* PD6 */ { 0, 0, 0, 0, 0, 0 }, /* PD6 */
+ /* PD5 */ { 0, 0, 0, 0, 0, 0 }, /* PD5 */
+#if 0
+ /* PD4 */ { 0, 0, 0, 0, 0, 0 }, /* PD4 */
+#else
+ /* PD4 */ { 1, 1, 1, 0, 0, 0 }, /* PD4 */
+#endif
+ /* PD3 */ { 0, 0, 0, 0, 0, 0 }, /* PD3 */
+ /* PD2 */ { 0, 0, 0, 0, 0, 0 }, /* PD2 */
+ /* PD1 */ { 0, 0, 0, 0, 0, 0 }, /* PD1 */
+ /* PD0 */ { 0, 0, 0, 0, 0, 0 } /* PD0 */
+ }
+};
+
+/*
+ * UPMB initialization table
+ */
+#define _NOT_USED_ 0xFFFFFFFF
+
+static const uint rtc_table[] =
+{
+ /*
+ * Single Read. (Offset 0 in UPMA RAM)
+ */
+ 0xfffec00, 0xfffac00, 0xfff2d00, 0xfef2800,
+ 0xfaf2080, 0xfaf2080, 0xfff2400, 0x1fff6c05, /* last */
+ /*
+ * Burst Read. (Offset 8 in UPMA RAM)
+ */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ /*
+ * Single Write. (Offset 18 in UPMA RAM)
+ */
+ 0xfffec00, 0xfffac00, 0xfff2d00, 0xfef2800,
+ 0xfaf2080, 0xfaf2080, 0xfaf2400, 0x1fbf6c05, /* last */
+ /*
+ * Burst Write. (Offset 20 in UPMA RAM)
+ */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ /*
+ * Refresh (Offset 30 in UPMA RAM)
+ */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+ /*
+ * Exception. (Offset 3c in UPMA RAM)
+ */
+ _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Check Board Identity:
+ */
+int checkboard (void)
+{
+ printf ("Board: ATC\n");
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Try SDRAM initialization with P/LSDMR=sdmr and ORx=orx
+ *
+ * This routine performs standard 8260 initialization sequence
+ * and calculates the available memory size. It may be called
+ * several times to try different SDRAM configurations on both
+ * 60x and local buses.
+ */
+static long int try_init (volatile memctl8260_t * memctl, ulong sdmr,
+ ulong orx, volatile uchar * base)
+{
+ volatile uchar c = 0xff;
+ volatile uint *sdmr_ptr;
+ volatile uint *orx_ptr;
+ ulong maxsize, size;
+ int i;
+
+ /* We must be able to test a location outsize the maximum legal size
+ * to find out THAT we are outside; but this address still has to be
+ * mapped by the controller. That means, that the initial mapping has
+ * to be (at least) twice as large as the maximum expected size.
+ */
+ maxsize = (1 + (~orx | 0x7fff)) / 2;
+
+ /* Since CONFIG_SYS_SDRAM_BASE is always 0 (??), we assume that
+ * we are configuring CS1 if base != 0
+ */
+ sdmr_ptr = &memctl->memc_psdmr;
+ orx_ptr = &memctl->memc_or2;
+
+ *orx_ptr = orx;
+
+ /*
+ * Quote from 8260 UM (10.4.2 SDRAM Power-On Initialization, 10-35):
+ *
+ * "At system reset, initialization software must set up the
+ * programmable parameters in the memory controller banks registers
+ * (ORx, BRx, P/LSDMR). After all memory parameters are configured,
+ * system software should execute the following initialization sequence
+ * for each SDRAM device.
+ *
+ * 1. Issue a PRECHARGE-ALL-BANKS command
+ * 2. Issue eight CBR REFRESH commands
+ * 3. Issue a MODE-SET command to initialize the mode register
+ *
+ * The initial commands are executed by setting P/LSDMR[OP] and
+ * accessing the SDRAM with a single-byte transaction."
+ *
+ * The appropriate BRx/ORx registers have already been set when we
+ * get here. The SDRAM can be accessed at the address CONFIG_SYS_SDRAM_BASE.
+ */
+
+ *sdmr_ptr = sdmr | PSDMR_OP_PREA;
+ *base = c;
+
+ *sdmr_ptr = sdmr | PSDMR_OP_CBRR;
+ for (i = 0; i < 8; i++)
+ *base = c;
+
+ *sdmr_ptr = sdmr | PSDMR_OP_MRW;
+ *(base + CONFIG_SYS_MRS_OFFS) = c; /* setting MR on address lines */
+
+ *sdmr_ptr = sdmr | PSDMR_OP_NORM | PSDMR_RFEN;
+ *base = c;
+
+ size = get_ram_size((long *)base, maxsize);
+
+ *orx_ptr = orx | ~(size - 1);
+
+ return (size);
+}
+
+int misc_init_r(void)
+{
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ volatile memctl8260_t *memctl = &immap->im_memctl;
+
+ upmconfig(UPMA, (uint *)rtc_table, sizeof(rtc_table) / sizeof(uint));
+ memctl->memc_mamr = MxMR_RLFx_6X | MxMR_WLFx_6X | MxMR_OP_NORM;
+
+ return (0);
+}
+
+phys_size_t initdram (int board_type)
+{
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ volatile memctl8260_t *memctl = &immap->im_memctl;
+
+#ifndef CONFIG_SYS_RAMBOOT
+ ulong size8, size9;
+#endif
+ long psize;
+
+ psize = 8 * 1024 * 1024;
+
+ memctl->memc_mptpr = CONFIG_SYS_MPTPR;
+ memctl->memc_psrt = CONFIG_SYS_PSRT;
+
+#ifndef CONFIG_SYS_RAMBOOT
+ /* 60x SDRAM setup:
+ */
+ size8 = try_init (memctl, CONFIG_SYS_PSDMR_8COL, CONFIG_SYS_OR2_8COL,
+ (uchar *) CONFIG_SYS_SDRAM_BASE);
+ size9 = try_init (memctl, CONFIG_SYS_PSDMR_9COL, CONFIG_SYS_OR2_9COL,
+ (uchar *) CONFIG_SYS_SDRAM_BASE);
+
+ if (size8 < size9) {
+ psize = size9;
+ printf ("(60x:9COL) ");
+ } else {
+ psize = try_init (memctl, CONFIG_SYS_PSDMR_8COL, CONFIG_SYS_OR2_8COL,
+ (uchar *) CONFIG_SYS_SDRAM_BASE);
+ printf ("(60x:8COL) ");
+ }
+
+#endif /* CONFIG_SYS_RAMBOOT */
+
+ icache_enable ();
+
+ return (psize);
+}
+
+#if defined(CONFIG_CMD_DOC)
+void doc_init (void)
+{
+ doc_probe (CONFIG_SYS_DOC_BASE);
+}
+#endif
+
+#ifdef CONFIG_PCI
+struct pci_controller hose;
+
+extern void pci_mpc8250_init(struct pci_controller *);
+
+void pci_init_board(void)
+{
+ pci_mpc8250_init(&hose);
+}
+#endif
diff --git a/qemu/roms/u-boot/board/atc/flash.c b/qemu/roms/u-boot/board/atc/flash.c
new file mode 100644
index 000000000..5a9c510c4
--- /dev/null
+++ b/qemu/roms/u-boot/board/atc/flash.c
@@ -0,0 +1,647 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
+
+/* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
+ * has nothing to do with the flash chip being 8-bit or 16-bit.
+ */
+#ifdef CONFIG_FLASH_16BIT
+typedef unsigned short FLASH_PORT_WIDTH;
+typedef volatile unsigned short FLASH_PORT_WIDTHV;
+#define FLASH_ID_MASK 0xFFFF
+#else
+typedef unsigned long FLASH_PORT_WIDTH;
+typedef volatile unsigned long FLASH_PORT_WIDTHV;
+#define FLASH_ID_MASK 0xFFFFFFFF
+#endif
+
+#define FPW FLASH_PORT_WIDTH
+#define FPWV FLASH_PORT_WIDTHV
+
+#define ORMASK(size) ((-size) & OR_AM_MSK)
+
+#define FLASH_CYCLE1 0x0555
+#define FLASH_CYCLE2 0x02aa
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size(FPWV *addr, flash_info_t *info);
+static void flash_reset(flash_info_t *info);
+static int write_word_intel(flash_info_t *info, FPWV *dest, FPW data);
+static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data);
+static void flash_get_offsets(ulong base, flash_info_t *info);
+static flash_info_t *flash_get_info(ulong base);
+
+/*-----------------------------------------------------------------------
+ * flash_init()
+ *
+ * sets up flash_info and returns size of FLASH (bytes)
+ */
+unsigned long flash_init (void)
+{
+ unsigned long size = 0;
+ int i;
+
+ /* Init: no FLASHes known */
+ for (i=0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
+#if 0
+ ulong flashbase = (i == 0) ? PHYS_FLASH_1 : PHYS_FLASH_2;
+#else
+ ulong flashbase = CONFIG_SYS_FLASH_BASE;
+#endif
+
+ memset(&flash_info[i], 0, sizeof(flash_info_t));
+
+ flash_info[i].size =
+ flash_get_size((FPW *)flashbase, &flash_info[i]);
+
+ if (flash_info[i].flash_id == FLASH_UNKNOWN) {
+ printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx\n",
+ i, flash_info[i].size);
+ }
+
+ size += flash_info[i].size;
+ }
+
+#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
+ /* monitor protection ON by default */
+ flash_protect(FLAG_PROTECT_SET,
+ CONFIG_SYS_MONITOR_BASE,
+ CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
+ flash_get_info(CONFIG_SYS_MONITOR_BASE));
+#endif
+
+#ifdef CONFIG_ENV_IS_IN_FLASH
+ /* ENV protection ON by default */
+ flash_protect(FLAG_PROTECT_SET,
+ CONFIG_ENV_ADDR,
+ CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
+ flash_get_info(CONFIG_ENV_ADDR));
+#endif
+
+
+ return size ? size : 1;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_reset(flash_info_t *info)
+{
+ FPWV *base = (FPWV *)(info->start[0]);
+
+ /* Put FLASH back in read mode */
+ if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
+ *base = (FPW)0x00FF00FF; /* Intel Read Mode */
+ else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
+ *base = (FPW)0x00F000F0; /* AMD Read Mode */
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+ int i;
+
+ /* set up sector start address table */
+ if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL
+ && (info->flash_id & FLASH_BTYPE)) {
+ int bootsect_size; /* number of bytes/boot sector */
+ int sect_size; /* number of bytes/regular sector */
+
+ bootsect_size = 0x00002000 * (sizeof(FPW)/2);
+ sect_size = 0x00010000 * (sizeof(FPW)/2);
+
+ /* set sector offsets for bottom boot block type */
+ for (i = 0; i < 8; ++i) {
+ info->start[i] = base + (i * bootsect_size);
+ }
+ for (i = 8; i < info->sector_count; i++) {
+ info->start[i] = base + ((i - 7) * sect_size);
+ }
+ }
+ else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
+
+ int sect_size; /* number of bytes/sector */
+
+ sect_size = 0x00010000 * (sizeof(FPW)/2);
+
+ /* set up sector start address table (uniform sector type) */
+ for( i = 0; i < info->sector_count; i++ )
+ info->start[i] = base + (i * sect_size);
+ }
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+static flash_info_t *flash_get_info(ulong base)
+{
+ int i;
+ flash_info_t * info;
+
+ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
+ info = & flash_info[i];
+ if (info->start[0] <= base && base < info->start[0] + info->size)
+ break;
+ }
+
+ return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+void flash_print_info (flash_info_t *info)
+{
+ int i;
+ uchar *boottype;
+ uchar *bootletter;
+ char *fmt;
+ uchar botbootletter[] = "B";
+ uchar topbootletter[] = "T";
+ uchar botboottype[] = "bottom boot sector";
+ uchar topboottype[] = "top boot sector";
+
+ 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_BM: printf ("BRIGHT MICRO "); break;
+ case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
+ case FLASH_MAN_SST: printf ("SST "); break;
+ case FLASH_MAN_STM: printf ("STM "); break;
+ case FLASH_MAN_INTEL: printf ("INTEL "); break;
+ default: printf ("Unknown Vendor "); break;
+ }
+
+ /* check for top or bottom boot, if it applies */
+ if (info->flash_id & FLASH_BTYPE) {
+ boottype = botboottype;
+ bootletter = botbootletter;
+ }
+ else {
+ boottype = topboottype;
+ bootletter = topbootletter;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_AM640U:
+ fmt = "29LV641D (64 Mbit, uniform sectors)\n";
+ break;
+ case FLASH_28F800C3B:
+ case FLASH_28F800C3T:
+ fmt = "28F800C3%s (8 Mbit, %s)\n";
+ break;
+ case FLASH_INTEL800B:
+ case FLASH_INTEL800T:
+ fmt = "28F800B3%s (8 Mbit, %s)\n";
+ break;
+ case FLASH_28F160C3B:
+ case FLASH_28F160C3T:
+ fmt = "28F160C3%s (16 Mbit, %s)\n";
+ break;
+ case FLASH_INTEL160B:
+ case FLASH_INTEL160T:
+ fmt = "28F160B3%s (16 Mbit, %s)\n";
+ break;
+ case FLASH_28F320C3B:
+ case FLASH_28F320C3T:
+ fmt = "28F320C3%s (32 Mbit, %s)\n";
+ break;
+ case FLASH_INTEL320B:
+ case FLASH_INTEL320T:
+ fmt = "28F320B3%s (32 Mbit, %s)\n";
+ break;
+ case FLASH_28F640C3B:
+ case FLASH_28F640C3T:
+ fmt = "28F640C3%s (64 Mbit, %s)\n";
+ break;
+ case FLASH_INTEL640B:
+ case FLASH_INTEL640T:
+ fmt = "28F640B3%s (64 Mbit, %s)\n";
+ break;
+ default:
+ fmt = "Unknown Chip Type\n";
+ break;
+ }
+
+ printf (fmt, bootletter, boottype);
+
+ printf (" Size: %ld MB in %d Sectors\n",
+ info->size >> 20,
+ info->sector_count);
+
+ printf (" Sector Start Addresses:");
+
+ for (i=0; i<info->sector_count; ++i) {
+ if ((i % 5) == 0) {
+ printf ("\n ");
+ }
+
+ printf (" %08lX%s", info->start[i],
+ info->protect[i] ? " (RO)" : " ");
+ }
+
+ printf ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+ulong flash_get_size (FPWV *addr, flash_info_t *info)
+{
+ /* Write auto select command: read Manufacturer ID */
+
+ /* Write auto select command sequence and test FLASH answer */
+ addr[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* for AMD, Intel ignores this */
+ addr[FLASH_CYCLE2] = (FPW)0x00550055; /* for AMD, Intel ignores this */
+ addr[FLASH_CYCLE1] = (FPW)0x00900090; /* selects Intel or AMD */
+
+ /* The manufacturer codes are only 1 byte, so just use 1 byte.
+ * This works for any bus width and any FLASH device width.
+ */
+ udelay(100);
+ switch (addr[0] & 0xff) {
+
+ case (uchar)AMD_MANUFACT:
+ info->flash_id = FLASH_MAN_AMD;
+ break;
+
+ case (uchar)INTEL_MANUFACT:
+ info->flash_id = FLASH_MAN_INTEL;
+ break;
+
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ break;
+ }
+
+ /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
+ if (info->flash_id != FLASH_UNKNOWN) switch (addr[1]) {
+
+ case (FPW)AMD_ID_LV640U: /* 29LV640 and 29LV641 have same ID */
+ info->flash_id += FLASH_AM640U;
+ info->sector_count = 128;
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+ break; /* => 8 or 16 MB */
+
+ case (FPW)INTEL_ID_28F800C3B:
+ info->flash_id += FLASH_28F800C3B;
+ info->sector_count = 23;
+ info->size = 0x00100000 * (sizeof(FPW)/2);
+ break; /* => 1 or 2 MB */
+
+ case (FPW)INTEL_ID_28F800B3B:
+ info->flash_id += FLASH_INTEL800B;
+ info->sector_count = 23;
+ info->size = 0x00100000 * (sizeof(FPW)/2);
+ break; /* => 1 or 2 MB */
+
+ case (FPW)INTEL_ID_28F160C3B:
+ info->flash_id += FLASH_28F160C3B;
+ info->sector_count = 39;
+ info->size = 0x00200000 * (sizeof(FPW)/2);
+ break; /* => 2 or 4 MB */
+
+ case (FPW)INTEL_ID_28F160B3B:
+ info->flash_id += FLASH_INTEL160B;
+ info->sector_count = 39;
+ info->size = 0x00200000 * (sizeof(FPW)/2);
+ break; /* => 2 or 4 MB */
+
+ case (FPW)INTEL_ID_28F320C3B:
+ info->flash_id += FLASH_28F320C3B;
+ info->sector_count = 71;
+ info->size = 0x00400000 * (sizeof(FPW)/2);
+ break; /* => 4 or 8 MB */
+
+ case (FPW)INTEL_ID_28F320B3B:
+ info->flash_id += FLASH_INTEL320B;
+ info->sector_count = 71;
+ info->size = 0x00400000 * (sizeof(FPW)/2);
+ break; /* => 4 or 8 MB */
+
+ case (FPW)INTEL_ID_28F640C3B:
+ info->flash_id += FLASH_28F640C3B;
+ info->sector_count = 135;
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+ break; /* => 8 or 16 MB */
+
+ case (FPW)INTEL_ID_28F640B3B:
+ info->flash_id += FLASH_INTEL640B;
+ info->sector_count = 135;
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+ break; /* => 8 or 16 MB */
+
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ return (0); /* => no or unknown flash */
+ }
+
+ flash_get_offsets((ulong)addr, info);
+
+ /* Put FLASH back in read mode */
+ flash_reset(info);
+
+ return (info->size);
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+ FPWV *addr;
+ int flag, prot, sect;
+ int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
+ ulong start, now, last;
+ int rcode = 0;
+
+ 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;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_INTEL800B:
+ case FLASH_INTEL160B:
+ case FLASH_INTEL320B:
+ case FLASH_INTEL640B:
+ case FLASH_28F800C3B:
+ case FLASH_28F160C3B:
+ case FLASH_28F320C3B:
+ case FLASH_28F640C3B:
+ case FLASH_AM640U:
+ break;
+ case FLASH_UNKNOWN:
+ default:
+ 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");
+ }
+
+ last = get_timer(0);
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect<=s_last && rcode == 0; sect++) {
+
+ if (info->protect[sect] != 0) /* protected, skip it */
+ continue;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ addr = (FPWV *)(info->start[sect]);
+ if (intel) {
+ *addr = (FPW)0x00500050; /* clear status register */
+ *addr = (FPW)0x00200020; /* erase setup */
+ *addr = (FPW)0x00D000D0; /* erase confirm */
+ }
+ else {
+ /* must be AMD style if not Intel */
+ FPWV *base; /* first address in bank */
+
+ base = (FPWV *)(info->start[0]);
+ base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */
+ base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */
+ base[FLASH_CYCLE1] = (FPW)0x00800080; /* erase mode */
+ base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */
+ base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */
+ *addr = (FPW)0x00300030; /* erase sector */
+ }
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer(0);
+
+ /* wait at least 50us for AMD, 80us for Intel.
+ * Let's wait 1 ms.
+ */
+ udelay (1000);
+
+ while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
+ if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
+ printf ("Timeout\n");
+
+ if (intel) {
+ /* suspend erase */
+ *addr = (FPW)0x00B000B0;
+ }
+
+ flash_reset(info); /* reset to read mode */
+ rcode = 1; /* failed */
+ break;
+ }
+
+ /* show that we're waiting */
+ if ((get_timer(last)) > CONFIG_SYS_HZ) {/* every second */
+ putc ('.');
+ last = get_timer(0);
+ }
+ }
+
+ /* show that we're waiting */
+ if ((get_timer(last)) > CONFIG_SYS_HZ) { /* every second */
+ putc ('.');
+ last = get_timer(0);
+ }
+
+ flash_reset(info); /* reset to read mode */
+ }
+
+ printf (" done\n");
+ return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ * 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)
+{
+ FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
+ int bytes; /* number of bytes to program in current word */
+ int left; /* number of bytes left to program */
+ int i, res;
+
+ for (left = cnt, res = 0;
+ left > 0 && res == 0;
+ addr += sizeof(data), left -= sizeof(data) - bytes) {
+
+ bytes = addr & (sizeof(data) - 1);
+ addr &= ~(sizeof(data) - 1);
+
+ /* combine source and destination data so can program
+ * an entire word of 16 or 32 bits
+ */
+ for (i = 0; i < sizeof(data); i++) {
+ data <<= 8;
+ if (i < bytes || i - bytes >= left )
+ data += *((uchar *)addr + i);
+ else
+ data += *src++;
+ }
+
+ /* write one word to the flash */
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_AMD:
+ res = write_word_amd(info, (FPWV *)addr, data);
+ break;
+ case FLASH_MAN_INTEL:
+ res = write_word_intel(info, (FPWV *)addr, data);
+ break;
+ default:
+ /* unknown flash type, error! */
+ printf ("missing or unknown FLASH type\n");
+ res = 1; /* not really a timeout, but gives error */
+ break;
+ }
+ }
+
+ return (res);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash for AMD FLASH
+ * A word is 16 or 32 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data)
+{
+ ulong start;
+ int flag;
+ int res = 0; /* result, assume success */
+ FPWV *base; /* first address in flash bank */
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*dest & data) != data) {
+ return (2);
+ }
+
+
+ base = (FPWV *)(info->start[0]);
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */
+ base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */
+ base[FLASH_CYCLE1] = (FPW)0x00A000A0; /* selects program mode */
+
+ *dest = data; /* start programming the data */
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer (0);
+
+ /* data polling for D7 */
+ while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
+ if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
+ *dest = (FPW)0x00F000F0; /* reset bank */
+ res = 1;
+ }
+ }
+
+ return (res);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash for Intel FLASH
+ * A word is 16 or 32 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word_intel (flash_info_t *info, FPWV *dest, FPW data)
+{
+ ulong start;
+ int flag;
+ int res = 0; /* result, assume success */
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*dest & data) != data) {
+ return (2);
+ }
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ *dest = (FPW)0x00500050; /* clear status register */
+ *dest = (FPW)0x00FF00FF; /* make sure in read mode */
+ *dest = (FPW)0x00400040; /* program setup */
+
+ *dest = data; /* start programming the data */
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer (0);
+
+ while (res == 0 && (*dest & (FPW)0x00800080) != (FPW)0x00800080) {
+ if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
+ *dest = (FPW)0x00B000B0; /* Suspend program */
+ res = 1;
+ }
+ }
+
+ if (res == 0 && (*dest & (FPW)0x00100010))
+ res = 1; /* write failed, time out error is close enough */
+
+ *dest = (FPW)0x00500050; /* clear status register */
+ *dest = (FPW)0x00FF00FF; /* make sure in read mode */
+
+ return (res);
+}
diff --git a/qemu/roms/u-boot/board/atc/ti113x.c b/qemu/roms/u-boot/board/atc/ti113x.c
new file mode 100644
index 000000000..c7c502ce4
--- /dev/null
+++ b/qemu/roms/u-boot/board/atc/ti113x.c
@@ -0,0 +1,620 @@
+/*
+ * (C) Copyright 2003-2005
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ ********************************************************************
+ *
+ * Lots of code copied from:
+ *
+ * i82365.c 1.352 - Linux driver for Intel 82365 and compatible
+ * PC Card controllers, and Yenta-compatible PCI-to-CardBus controllers.
+ * (C) 1999 David A. Hinds <dahinds@users.sourceforge.net>
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_I82365
+
+#include <command.h>
+#include <pci.h>
+#include <pcmcia.h>
+#include <asm/io.h>
+
+#include <pcmcia/ss.h>
+#include <pcmcia/i82365.h>
+#include <pcmcia/yenta.h>
+#include <pcmcia/ti113x.h>
+
+static struct pci_device_id supported[] = {
+ {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1510},
+ {0, 0}
+};
+
+#define CYCLE_TIME 120
+
+#ifdef DEBUG
+static void i82365_dump_regions (pci_dev_t dev);
+#endif
+
+typedef struct socket_info_t {
+ pci_dev_t dev;
+ u_short bcr;
+ u_char pci_lat, cb_lat, sub_bus, cache;
+ u_int cb_phys;
+
+ socket_cap_t cap;
+ u_short type;
+ u_int flags;
+ ti113x_state_t state;
+} socket_info_t;
+
+static socket_info_t socket;
+static socket_state_t state;
+static struct pccard_mem_map mem;
+static struct pccard_io_map io;
+
+/*====================================================================*/
+
+/* Some PCI shortcuts */
+
+static int pci_readb (socket_info_t * s, int r, u_char * v)
+{
+ return pci_read_config_byte (s->dev, r, v);
+}
+static int pci_writeb (socket_info_t * s, int r, u_char v)
+{
+ return pci_write_config_byte (s->dev, r, v);
+}
+static int pci_readw (socket_info_t * s, int r, u_short * v)
+{
+ return pci_read_config_word (s->dev, r, v);
+}
+static int pci_writew (socket_info_t * s, int r, u_short v)
+{
+ return pci_write_config_word (s->dev, r, v);
+}
+static int pci_readl (socket_info_t * s, int r, u_int * v)
+{
+ return pci_read_config_dword (s->dev, r, v);
+}
+static int pci_writel (socket_info_t * s, int r, u_int v)
+{
+ return pci_write_config_dword (s->dev, r, v);
+}
+
+/*====================================================================*/
+
+#define cb_readb(s, r) readb((s)->cb_phys + (r))
+#define cb_readl(s, r) readl((s)->cb_phys + (r))
+#define cb_writeb(s, r, v) writeb(v, (s)->cb_phys + (r))
+#define cb_writel(s, r, v) writel(v, (s)->cb_phys + (r))
+
+static u_char i365_get (socket_info_t * s, u_short reg)
+{
+ return cb_readb (s, 0x0800 + reg);
+}
+
+static void i365_set (socket_info_t * s, u_short reg, u_char data)
+{
+ cb_writeb (s, 0x0800 + reg, data);
+}
+
+static void i365_bset (socket_info_t * s, u_short reg, u_char mask)
+{
+ i365_set (s, reg, i365_get (s, reg) | mask);
+}
+
+static void i365_bclr (socket_info_t * s, u_short reg, u_char mask)
+{
+ i365_set (s, reg, i365_get (s, reg) & ~mask);
+}
+
+#if 0 /* not used */
+static void i365_bflip (socket_info_t * s, u_short reg, u_char mask, int b)
+{
+ u_char d = i365_get (s, reg);
+
+ i365_set (s, reg, (b) ? (d | mask) : (d & ~mask));
+}
+
+static u_short i365_get_pair (socket_info_t * s, u_short reg)
+{
+ return (i365_get (s, reg) + (i365_get (s, reg + 1) << 8));
+}
+#endif /* not used */
+
+static void i365_set_pair (socket_info_t * s, u_short reg, u_short data)
+{
+ i365_set (s, reg, data & 0xff);
+ i365_set (s, reg + 1, data >> 8);
+}
+
+/*======================================================================
+
+ Code to save and restore global state information for TI 1130 and
+ TI 1131 controllers, and to set and report global configuration
+ options.
+
+======================================================================*/
+
+static void ti113x_get_state (socket_info_t * s)
+{
+ ti113x_state_t *p = &s->state;
+
+ pci_readl (s, TI113X_SYSTEM_CONTROL, &p->sysctl);
+ pci_readb (s, TI113X_CARD_CONTROL, &p->cardctl);
+ pci_readb (s, TI113X_DEVICE_CONTROL, &p->devctl);
+ pci_readb (s, TI1250_DIAGNOSTIC, &p->diag);
+ pci_readl (s, TI12XX_IRQMUX, &p->irqmux);
+}
+
+static void ti113x_set_state (socket_info_t * s)
+{
+ ti113x_state_t *p = &s->state;
+
+ pci_writel (s, TI113X_SYSTEM_CONTROL, p->sysctl);
+ pci_writeb (s, TI113X_CARD_CONTROL, p->cardctl);
+ pci_writeb (s, TI113X_DEVICE_CONTROL, p->devctl);
+ pci_writeb (s, TI1250_MULTIMEDIA_CTL, 0);
+ pci_writeb (s, TI1250_DIAGNOSTIC, p->diag);
+ pci_writel (s, TI12XX_IRQMUX, p->irqmux);
+ i365_set_pair (s, TI113X_IO_OFFSET (0), 0);
+ i365_set_pair (s, TI113X_IO_OFFSET (1), 0);
+}
+
+static u_int ti113x_set_opts (socket_info_t * s)
+{
+ ti113x_state_t *p = &s->state;
+ u_int mask = 0xffff;
+
+ p->cardctl &= ~TI113X_CCR_ZVENABLE;
+ p->cardctl |= TI113X_CCR_SPKROUTEN;
+
+ return mask;
+}
+
+/*======================================================================
+
+ Routines to handle common CardBus options
+
+======================================================================*/
+
+/* Default settings for PCI command configuration register */
+#define CMD_DFLT (PCI_COMMAND_IO|PCI_COMMAND_MEMORY| \
+ PCI_COMMAND_MASTER|PCI_COMMAND_WAIT)
+
+static void cb_get_state (socket_info_t * s)
+{
+ pci_readb (s, PCI_CACHE_LINE_SIZE, &s->cache);
+ pci_readb (s, PCI_LATENCY_TIMER, &s->pci_lat);
+ pci_readb (s, CB_LATENCY_TIMER, &s->cb_lat);
+ pci_readb (s, CB_CARDBUS_BUS, &s->cap.cardbus);
+ pci_readb (s, CB_SUBORD_BUS, &s->sub_bus);
+ pci_readw (s, CB_BRIDGE_CONTROL, &s->bcr);
+}
+
+static void cb_set_state (socket_info_t * s)
+{
+ pci_writel (s, CB_LEGACY_MODE_BASE, 0);
+ pci_writel (s, PCI_BASE_ADDRESS_0, s->cb_phys);
+ pci_writew (s, PCI_COMMAND, CMD_DFLT);
+ pci_writeb (s, PCI_CACHE_LINE_SIZE, s->cache);
+ pci_writeb (s, PCI_LATENCY_TIMER, s->pci_lat);
+ pci_writeb (s, CB_LATENCY_TIMER, s->cb_lat);
+ pci_writeb (s, CB_CARDBUS_BUS, s->cap.cardbus);
+ pci_writeb (s, CB_SUBORD_BUS, s->sub_bus);
+ pci_writew (s, CB_BRIDGE_CONTROL, s->bcr);
+}
+
+static void cb_set_opts (socket_info_t * s)
+{
+ if (s->cache == 0)
+ s->cache = 8;
+ if (s->pci_lat == 0)
+ s->pci_lat = 0xa8;
+ if (s->cb_lat == 0)
+ s->cb_lat = 0xb0;
+}
+
+/*======================================================================
+
+ Power control for Cardbus controllers: used both for 16-bit and
+ Cardbus cards.
+
+======================================================================*/
+
+static int cb_set_power (socket_info_t * s, socket_state_t * state)
+{
+ u_int reg = 0;
+
+ /* restart card voltage detection if it seems appropriate */
+ if ((state->Vcc == 0) && (state->Vpp == 0) &&
+ !(cb_readl (s, CB_SOCKET_STATE) & CB_SS_VSENSE))
+ cb_writel (s, CB_SOCKET_FORCE, CB_SF_CVSTEST);
+ switch (state->Vcc) {
+ case 0:
+ reg = 0;
+ break;
+ case 33:
+ reg = CB_SC_VCC_3V;
+ break;
+ case 50:
+ reg = CB_SC_VCC_5V;
+ break;
+ default:
+ return -1;
+ }
+ switch (state->Vpp) {
+ case 0:
+ break;
+ case 33:
+ reg |= CB_SC_VPP_3V;
+ break;
+ case 50:
+ reg |= CB_SC_VPP_5V;
+ break;
+ case 120:
+ reg |= CB_SC_VPP_12V;
+ break;
+ default:
+ return -1;
+ }
+ if (reg != cb_readl (s, CB_SOCKET_CONTROL))
+ cb_writel (s, CB_SOCKET_CONTROL, reg);
+
+ return 0;
+}
+
+/*======================================================================
+
+ Generic routines to get and set controller options
+
+======================================================================*/
+
+static void get_bridge_state (socket_info_t * s)
+{
+ ti113x_get_state (s);
+ cb_get_state (s);
+}
+
+static void set_bridge_state (socket_info_t * s)
+{
+ cb_set_state (s);
+ i365_set (s, I365_GBLCTL, 0x00);
+ i365_set (s, I365_GENCTL, 0x00);
+ ti113x_set_state (s);
+}
+
+static void set_bridge_opts (socket_info_t * s)
+{
+ ti113x_set_opts (s);
+ cb_set_opts (s);
+}
+
+/*====================================================================*/
+#define PD67_EXT_INDEX 0x2e /* Extension index */
+#define PD67_EXT_DATA 0x2f /* Extension data */
+#define PD67_EXD_VS1(s) (0x01 << ((s)<<1))
+
+#define pd67_ext_get(s, r) \
+ (i365_set(s, PD67_EXT_INDEX, r), i365_get(s, PD67_EXT_DATA))
+
+static int i365_get_status (socket_info_t * s, u_int * value)
+{
+ u_int status;
+
+ status = i365_get (s, I365_IDENT);
+ status = i365_get (s, I365_STATUS);
+ *value = ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0;
+ if (i365_get (s, I365_INTCTL) & I365_PC_IOCARD) {
+ *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
+ } else {
+ *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
+ *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
+ }
+ *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
+ *value |= (status & I365_CS_READY) ? SS_READY : 0;
+ *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
+
+ status = cb_readl (s, CB_SOCKET_STATE);
+ *value |= (status & CB_SS_32BIT) ? SS_CARDBUS : 0;
+ *value |= (status & CB_SS_3VCARD) ? SS_3VCARD : 0;
+ *value |= (status & CB_SS_XVCARD) ? SS_XVCARD : 0;
+ *value |= (status & CB_SS_VSENSE) ? 0 : SS_PENDING;
+ /* For now, ignore cards with unsupported voltage keys */
+ if (*value & SS_XVCARD)
+ *value &= ~(SS_DETECT | SS_3VCARD | SS_XVCARD);
+
+ return 0;
+} /* i365_get_status */
+
+static int i365_set_socket (socket_info_t * s, socket_state_t * state)
+{
+ u_char reg;
+
+ set_bridge_state (s);
+
+ /* IO card, RESET flag */
+ reg = 0;
+ reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
+ reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
+ i365_set (s, I365_INTCTL, reg);
+
+ reg = I365_PWR_NORESET;
+ if (state->flags & SS_PWR_AUTO)
+ reg |= I365_PWR_AUTO;
+ if (state->flags & SS_OUTPUT_ENA)
+ reg |= I365_PWR_OUT;
+
+ cb_set_power (s, state);
+ reg |= i365_get (s, I365_POWER) & (I365_VCC_MASK | I365_VPP1_MASK);
+
+ if (reg != i365_get (s, I365_POWER))
+ i365_set (s, I365_POWER, reg);
+
+ return 0;
+} /* i365_set_socket */
+
+/*====================================================================*/
+
+static int i365_set_mem_map (socket_info_t * s, struct pccard_mem_map *mem)
+{
+ u_short base, i;
+ u_char map;
+
+ debug ("i82365: SetMemMap(%d, %#2.2x, %d ns, %#5.5lx-%#5.5lx, %#5.5x)\n",
+ mem->map, mem->flags, mem->speed,
+ mem->sys_start, mem->sys_stop, mem->card_start);
+
+ map = mem->map;
+ if ((map > 4) ||
+ (mem->card_start > 0x3ffffff) ||
+ (mem->sys_start > mem->sys_stop) ||
+ (mem->speed > 1000)) {
+ return -1;
+ }
+
+ /* Turn off the window before changing anything */
+ if (i365_get (s, I365_ADDRWIN) & I365_ENA_MEM (map))
+ i365_bclr (s, I365_ADDRWIN, I365_ENA_MEM (map));
+
+ /* Take care of high byte, for PCI controllers */
+ i365_set (s, CB_MEM_PAGE (map), mem->sys_start >> 24);
+
+ base = I365_MEM (map);
+ i = (mem->sys_start >> 12) & 0x0fff;
+ if (mem->flags & MAP_16BIT)
+ i |= I365_MEM_16BIT;
+ if (mem->flags & MAP_0WS)
+ i |= I365_MEM_0WS;
+ i365_set_pair (s, base + I365_W_START, i);
+
+ i = (mem->sys_stop >> 12) & 0x0fff;
+ switch (mem->speed / CYCLE_TIME) {
+ case 0:
+ break;
+ case 1:
+ i |= I365_MEM_WS0;
+ break;
+ case 2:
+ i |= I365_MEM_WS1;
+ break;
+ default:
+ i |= I365_MEM_WS1 | I365_MEM_WS0;
+ break;
+ }
+ i365_set_pair (s, base + I365_W_STOP, i);
+
+ i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
+ if (mem->flags & MAP_WRPROT)
+ i |= I365_MEM_WRPROT;
+ if (mem->flags & MAP_ATTRIB)
+ i |= I365_MEM_REG;
+ i365_set_pair (s, base + I365_W_OFF, i);
+
+ /* Turn on the window if necessary */
+ if (mem->flags & MAP_ACTIVE)
+ i365_bset (s, I365_ADDRWIN, I365_ENA_MEM (map));
+ return 0;
+} /* i365_set_mem_map */
+
+static int i365_set_io_map (socket_info_t * s, struct pccard_io_map *io)
+{
+ u_char map, ioctl;
+
+ map = io->map;
+ /* comment out: comparison is always false due to limited range of data type */
+ if ((map > 1) || /* (io->start > 0xffff) || (io->stop > 0xffff) || */
+ (io->stop < io->start))
+ return -1;
+ /* Turn off the window before changing anything */
+ if (i365_get (s, I365_ADDRWIN) & I365_ENA_IO (map))
+ i365_bclr (s, I365_ADDRWIN, I365_ENA_IO (map));
+ i365_set_pair (s, I365_IO (map) + I365_W_START, io->start);
+ i365_set_pair (s, I365_IO (map) + I365_W_STOP, io->stop);
+ ioctl = i365_get (s, I365_IOCTL) & ~I365_IOCTL_MASK (map);
+ if (io->speed)
+ ioctl |= I365_IOCTL_WAIT (map);
+ if (io->flags & MAP_0WS)
+ ioctl |= I365_IOCTL_0WS (map);
+ if (io->flags & MAP_16BIT)
+ ioctl |= I365_IOCTL_16BIT (map);
+ if (io->flags & MAP_AUTOSZ)
+ ioctl |= I365_IOCTL_IOCS16 (map);
+ i365_set (s, I365_IOCTL, ioctl);
+ /* Turn on the window if necessary */
+ if (io->flags & MAP_ACTIVE)
+ i365_bset (s, I365_ADDRWIN, I365_ENA_IO (map));
+ return 0;
+} /* i365_set_io_map */
+
+/*====================================================================*/
+
+static int i82365_init (void)
+{
+ u_int val;
+ int i;
+
+ if ((socket.dev = pci_find_devices (supported, 0)) < 0) {
+ /* Controller not found */
+ return 1;
+ }
+ debug ("i82365 Device Found!\n");
+
+ pci_read_config_dword (socket.dev, PCI_BASE_ADDRESS_0, &socket.cb_phys);
+ socket.cb_phys &= ~0xf;
+
+ get_bridge_state (&socket);
+ set_bridge_opts (&socket);
+
+ i = i365_get_status (&socket, &val);
+
+ if (val & SS_DETECT) {
+ if (val & SS_3VCARD) {
+ state.Vcc = state.Vpp = 33;
+ puts (" 3.3V card found: ");
+ } else if (!(val & SS_XVCARD)) {
+ state.Vcc = state.Vpp = 50;
+ puts (" 5.0V card found: ");
+ } else {
+ puts ("i82365: unsupported voltage key\n");
+ state.Vcc = state.Vpp = 0;
+ }
+ } else {
+ /* No card inserted */
+ puts ("No card\n");
+ return 1;
+ }
+
+ state.flags = SS_IOCARD | SS_OUTPUT_ENA;
+ state.csc_mask = 0;
+ state.io_irq = 0;
+
+ i365_set_socket (&socket, &state);
+
+ for (i = 500; i; i--) {
+ if ((i365_get (&socket, I365_STATUS) & I365_CS_READY))
+ break;
+ udelay (1000);
+ }
+
+ if (i == 0) {
+ /* PC Card not ready for data transfer */
+ puts ("i82365 PC Card not ready for data transfer\n");
+ return 1;
+ }
+ debug (" PC Card ready for data transfer: ");
+
+ mem.map = 0;
+ mem.flags = MAP_ATTRIB | MAP_ACTIVE;
+ mem.speed = 300;
+ mem.sys_start = CONFIG_SYS_PCMCIA_MEM_ADDR;
+ mem.sys_stop = CONFIG_SYS_PCMCIA_MEM_ADDR + CONFIG_SYS_PCMCIA_MEM_SIZE - 1;
+ mem.card_start = 0;
+ i365_set_mem_map (&socket, &mem);
+
+ io.map = 0;
+ io.flags = MAP_AUTOSZ | MAP_ACTIVE;
+ io.speed = 0;
+ io.start = 0x0100;
+ io.stop = 0x010F;
+ i365_set_io_map (&socket, &io);
+
+#ifdef DEBUG
+ i82365_dump_regions (socket.dev);
+#endif
+
+ return 0;
+}
+
+static void i82365_exit (void)
+{
+ io.map = 0;
+ io.flags = 0;
+ io.speed = 0;
+ io.start = 0;
+ io.stop = 0x1;
+
+ i365_set_io_map (&socket, &io);
+
+ mem.map = 0;
+ mem.flags = 0;
+ mem.speed = 0;
+ mem.sys_start = 0;
+ mem.sys_stop = 0x1000;
+ mem.card_start = 0;
+
+ i365_set_mem_map (&socket, &mem);
+
+ socket.state.sysctl &= 0xFFFF00FF;
+
+ state.Vcc = state.Vpp = 0;
+
+ i365_set_socket (&socket, &state);
+}
+
+int pcmcia_on (void)
+{
+ u_int rc;
+
+ debug ("Enable PCMCIA " PCMCIA_SLOT_MSG "\n");
+
+ rc = i82365_init();
+ if (rc)
+ goto exit;
+
+ rc = check_ide_device(0);
+ if (rc == 0)
+ goto exit;
+
+ i82365_exit();
+
+exit:
+ return rc;
+}
+
+#if defined(CONFIG_CMD_PCMCIA)
+int pcmcia_off (void)
+{
+ printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n");
+
+ i82365_exit();
+
+ return 0;
+}
+#endif
+
+/*======================================================================
+
+ Debug stuff
+
+======================================================================*/
+
+#ifdef DEBUG
+static void i82365_dump_regions (pci_dev_t dev)
+{
+ u_int tmp[2];
+ u_int *mem = (void *) socket.cb_phys;
+ u_char *cis = (void *) CONFIG_SYS_PCMCIA_MEM_ADDR;
+ u_char *ide = (void *) (CONFIG_SYS_ATA_BASE_ADDR + CONFIG_SYS_ATA_REG_OFFSET);
+
+ pci_read_config_dword (dev, 0x00, tmp + 0);
+ pci_read_config_dword (dev, 0x80, tmp + 1);
+
+ printf ("PCI CONF: %08X ... %08X\n",
+ tmp[0], tmp[1]);
+ printf ("PCI MEM: ... %08X ... %08X\n",
+ mem[0x8 / 4], mem[0x800 / 4]);
+ printf ("CIS: ...%c%c%c%c%c%c%c%c...\n",
+ cis[0x38], cis[0x3a], cis[0x3c], cis[0x3e],
+ cis[0x40], cis[0x42], cis[0x44], cis[0x48]);
+ printf ("CIS CONF: %02X %02X %02X ...\n",
+ cis[0x200], cis[0x202], cis[0x204]);
+ printf ("IDE: %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ ide[0], ide[1], ide[2], ide[3],
+ ide[4], ide[5], ide[6], ide[7]);
+}
+#endif /* DEBUG */
+
+#endif /* CONFIG_I82365 */