All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matthias Fuchs <matthias.fuchs@esd-electronics.com>
To: u-boot@lists.denx.de
Subject: [U-Boot-Users] [PATCH 4/5] ppc4xx: Add FPGA support and BSP command for PMC440 boards
Date: Mon, 12 Nov 2007 15:58:12 +0100	[thread overview]
Message-ID: <200711121558.12990.matthias.fuchs@esd-electronics.com> (raw)
In-Reply-To: <11947848441043-git-send-email-matthias.fuchs@esd-electronics.com>

Hi,

Stefan motivated me to resend this patch with some whitespace issues fixed.

This patch adds some BSP commands and FPGA booting support
for esd's PMC440 boards.

Signed-off-by: Matthias Fuchs <matthias.fuchs@esd-electronics.com>
---
 board/esd/pmc440/cmd_pmc440.c |  555 +++++++++++++++++++++++++++++++++++++++++
 board/esd/pmc440/fpga.c       |  469 ++++++++++++++++++++++++++++++++++
 board/esd/pmc440/fpga.h       |   47 ++++
 3 files changed, 1071 insertions(+), 0 deletions(-)
 create mode 100644 board/esd/pmc440/cmd_pmc440.c
 create mode 100644 board/esd/pmc440/fpga.c
 create mode 100644 board/esd/pmc440/fpga.h

diff --git a/board/esd/pmc440/cmd_pmc440.c b/board/esd/pmc440/cmd_pmc440.c
new file mode 100644
index 0000000..0480ece
--- /dev/null
+++ b/board/esd/pmc440/cmd_pmc440.c
@@ -0,0 +1,555 @@
+/*
+ * (C) Copyright 2007
+ * Matthias Fuchs, esd Gmbh, matthias.fuchs at esd-electronics.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+
+#include <asm/processor.h>
+
+#include "pmc440.h"
+
+int is_monarch(void);
+int bootstrap_eeprom_write(unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt);
+int eeprom_write_enable(unsigned dev_addr, int state);
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_CMD_BSP
+
+static int got_fifoirq;
+static int got_hcirq;
+
+int fpga_interrupt(u32 arg)
+{
+	pmc440_fpga_t *fpga = (pmc440_fpga_t *)arg;
+	int rc = -1; /* not for us */
+	u32 status = FPGA_IN32(&fpga->status);
+
+	/* check for interrupt from fifo module */
+	if (status & STATUS_FIFO_ISF) {
+		/* disable this int source */
+		FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_FIFOIE_GATE);
+		rc = 0;
+		got_fifoirq = 1; /* trigger backend */
+	}
+
+	if (status & STATUS_HOST_ISF) {
+		FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_HCINT_GATE);
+		rc = 0;
+		got_hcirq = 1;
+	}
+
+	return rc;
+}
+
+
+int do_waithci(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+	got_hcirq = 0;
+
+	FPGA_CLRBITS(&fpga->ctrla, CTRL_HOST_IE);
+	FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_HCINT_GATE);
+
+	irq_install_handler(IRQ0_FPGA,
+			    (interrupt_handler_t *)fpga_interrupt,
+			    fpga);
+
+	FPGA_SETBITS(&fpga->ctrla, CTRL_HOST_IE);
+
+	while (!got_hcirq) {
+		/* Abort if ctrl-c was pressed */
+		if (ctrlc()) {
+			puts("\nAbort\n");
+			break;
+		}
+	}
+	if (got_hcirq)
+		printf("Got interrupt!\n");
+
+	FPGA_CLRBITS(&fpga->ctrla, CTRL_HOST_IE);
+	irq_free_handler(IRQ0_FPGA);
+	return 0;
+}
+U_BOOT_CMD(
+	waithci,	1,	1,	do_waithci,
+	"waithci - Wait for host control interrupt\n",
+	NULL
+	);
+
+
+void dump_fifo(pmc440_fpga_t *fpga, int f, int *n)
+{
+	u32 ctrl;
+
+	while (!((ctrl = FPGA_IN32(&fpga->fifo[f].ctrl)) & FIFO_EMPTY)) {
+		printf("%5d  %d    %3d  %08x",
+		       (*n)++, f, ctrl & (FIFO_LEVEL_MASK | FIFO_FULL),
+		       FPGA_IN32(&fpga->fifo[f].data));
+		if (ctrl & FIFO_OVERFLOW) {
+			printf(" OVERFLOW\n");
+			FPGA_CLRBITS(&fpga->fifo[f].ctrl, FIFO_OVERFLOW);
+		} else
+			printf("\n");
+	}
+}
+
+
+int do_fifo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+	int i;
+	int n = 0;
+	u32 ctrl, data, f;
+	char str[] = "\\|/-";
+	int abort = 0;
+	int count = 0;
+	int count2 = 0;
+
+	switch (argc) {
+	case 1:
+		/* print all fifos status information */
+		printf("fifo level status\n");
+		printf("______________________________\n");
+		for (i=0; i<FIFO_COUNT; i++) {
+			ctrl = FPGA_IN32(&fpga->fifo[i].ctrl);
+			printf(" %d    %3d  %s%s%s %s\n",
+			       i, ctrl & (FIFO_LEVEL_MASK | FIFO_FULL),
+			       ctrl & FIFO_FULL ? "FULL     " : "",
+			       ctrl & FIFO_EMPTY ? "EMPTY    " : "",
+			       ctrl & (FIFO_FULL|FIFO_EMPTY) ? "" : "NOT EMPTY",
+			       ctrl & FIFO_OVERFLOW ? "OVERFLOW" : "");
+		}
+		break;
+
+	case 2:
+		/* completely read out fifo 'n' */
+		if (!strcmp(argv[1],"read")) {
+			printf("  #   fifo level data\n");
+			printf("______________________________\n");
+
+			for (i=0; i<FIFO_COUNT; i++)
+				dump_fifo(fpga, i, &n);
+
+		} else if (!strcmp(argv[1],"wait")) {
+			got_fifoirq = 0;
+
+			irq_install_handler(IRQ0_FPGA,
+					    (interrupt_handler_t *)fpga_interrupt,
+					    fpga);
+
+			printf("  #   fifo level data\n");
+			printf("______________________________\n");
+
+			/* enable all fifo interrupts */
+			FPGA_OUT32(&fpga->hostctrl,
+				   HOSTCTRL_FIFOIE_GATE | HOSTCTRL_FIFOIE_FLAG);
+			for (i=0; i<FIFO_COUNT; i++) {
+				/* enable interrupts from all fifos */
+				FPGA_SETBITS(&fpga->fifo[i].ctrl, FIFO_IE);
+			}
+
+			while (1) {
+				/* wait loop */
+				while (!got_fifoirq) {
+					count++;
+					if (!(count % 100)) {
+						count2++;
+						putc(0x08); /* backspace */
+						putc(str[count2 % 4]);
+					}
+
+					/* Abort if ctrl-c was pressed */
+					if ((abort = ctrlc())) {
+						puts("\nAbort\n");
+						break;
+					}
+					udelay(1000);
+				}
+				if (abort)
+					break;
+
+				/* simple fifo backend */
+				if (got_fifoirq) {
+					for (i=0; i<FIFO_COUNT; i++)
+						dump_fifo(fpga, i, &n);
+
+					got_fifoirq = 0;
+					/* unmask global fifo irq */
+					FPGA_OUT32(&fpga->hostctrl,
+						   HOSTCTRL_FIFOIE_GATE | HOSTCTRL_FIFOIE_FLAG);
+				}
+			}
+
+			/* disable all fifo interrupts */
+			FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_FIFOIE_GATE);
+			for (i=0; i<FIFO_COUNT; i++)
+				FPGA_CLRBITS(&fpga->fifo[i].ctrl, FIFO_IE);
+
+			irq_free_handler(IRQ0_FPGA);
+
+		} else {
+			printf("Usage:\nfifo %s\n", cmdtp->help);
+			return 1;
+		}
+		break;
+
+	case 4:
+	case 5:
+		if (!strcmp(argv[1],"write")) {
+			/* get fifo number or fifo address */
+			f = simple_strtoul(argv[2], NULL, 16);
+
+			/* data paramter */
+			data = simple_strtoul(argv[3], NULL, 16);
+
+			/* get optional count parameter */
+			n = 1;
+			if (argc >= 5)
+				n = (int)simple_strtoul(argv[4], NULL, 10);
+
+			if (f < FIFO_COUNT) {
+				printf("writing %d x %08x to fifo %d\n",
+				       n, data, f);
+				for (i=0; i<n; i++)
+					FPGA_OUT32(&fpga->fifo[f].data, data);
+			} else {
+				printf("writing %d x %08x to fifo port at address %08x\n",
+				       n, data, f);
+				for (i=0; i<n; i++)
+					out32(f, data);
+			}
+		} else {
+			printf("Usage:\nfifo %s\n", cmdtp->help);
+			return 1;
+		}
+		break;
+
+	default:
+		printf("Usage:\nfifo %s\n", cmdtp->help);
+		return 1;
+	}
+	return 0;
+}
+U_BOOT_CMD(
+	fifo,	5,	1,	do_fifo,
+	"fifo    - Fifo module operations\n",
+	"wait\nfifo read\n"
+	"fifo write fifo(0..3) data [cnt=1]\n"
+	"fifo write address(>=4) data [cnt=1]\n"
+	"  - without arguments: print all fifo's status\n"
+	"  - with 'wait' argument: interrupt driven read from all fifos\n"
+	"  - with 'read' argument: read current contents from all fifos\n"
+	"  - with 'write' argument: write 'data' 'cnt' times to 'fifo' or 'address'\n"
+	);
+
+
+int do_setup_bootstrap_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	ulong sdsdp[5];
+	ulong delay;
+	int count=16;
+
+	if (argc < 2) {
+		printf("Usage:\nsbe %s\n", cmdtp->help);
+		return -1;
+	}
+
+	if (argc > 1) {
+		if (!strcmp(argv[1], "400")) {
+			/* PLB=133MHz, PLB/PCI=4 */
+			printf("Bootstrapping for 400MHz\n");
+			sdsdp[0]=0x8678624e;
+			sdsdp[1]=0x0947a030;
+			sdsdp[2]=0x40082350;
+			sdsdp[3]=0x0d050000;
+		} else if (!strcmp(argv[1], "533")) {
+			/* PLB=133MHz, PLB/PCI=3 */
+			printf("Bootstrapping for 533MHz\n");
+			sdsdp[0]=0x87788252;
+			sdsdp[1]=0x095fa030;
+			sdsdp[2]=0x40082350;
+			sdsdp[3]=0x0d050000;
+		} else if (!strcmp(argv[1], "667")) {
+			/* PLB=133MHz, PLB/PCI=4 */
+			printf("Bootstrapping for 667MHz\n");
+			sdsdp[0]=0x8778a256;
+			sdsdp[1]=0x0947a030;
+			sdsdp[2]=0x40082350;
+			sdsdp[3]=0x0d050000;
+		} else if (!strcmp(argv[1], "test")) {
+			/* TODO: this will replace the 667 MHz config above.
+			 * But it needs some more testing on a real 667 MHz CPU.
+			 */
+			printf("Bootstrapping for test (667MHz PLB=133PLB PLB/PCI=3)\n");
+			sdsdp[0]=0x8778a256;
+			sdsdp[1]=0x095fa030;
+			sdsdp[2]=0x40082350;
+			sdsdp[3]=0x0d050000;
+		} else {
+			printf("Usage:\nsbe %s\n", cmdtp->help);
+			return -1;
+		}
+	}
+
+	if (argc > 2) {
+		sdsdp[4] = 0;
+		if (argv[2][0]=='1')
+			sdsdp[4]=0x19750100;
+		else if (argv[2][0]=='0')
+			sdsdp[4]=0x19750000;
+		if (sdsdp[4])
+			count += 4;
+	}
+
+	if (argc > 3) {
+		delay = simple_strtoul(argv[3], NULL, 10);
+		if (delay > 20)
+			delay = 20;
+		sdsdp[4] |= delay;
+	}
+
+	printf("Writing boot EEPROM ...\n");
+	if (bootstrap_eeprom_write(CFG_I2C_BOOT_EEPROM_ADDR,
+				   0, (uchar*)sdsdp, count) != 0)
+		printf("bootstrap_eeprom_write failed\n");
+	else
+		printf("done (dump via 'i2c md 52 0.1 14')\n");
+
+	return 0;
+}
+U_BOOT_CMD(
+	sbe, 4, 0, do_setup_bootstrap_eeprom,
+	"sbe     - setup bootstrap eeprom\n",
+	"<cpufreq:400|533|667> [<console-uart:0|1> [<bringup delay (0..20s)>]]"
+	);
+
+
+#ifdef CONFIG_PRAM
+#include <environment.h>
+extern env_t *env_ptr;
+
+int do_painit(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	u32 memsize;
+	u32 pram;
+	char *v;
+	u32 param;
+	ulong *lptr;
+
+	memsize = gd->bd->bi_memsize;
+
+	v = getenv("pram");
+	if (v)
+		pram = simple_strtoul(v, NULL, 10);
+	else {
+		printf("Error: pram undefined. Please define pram in KiB\n");
+		return 1;
+	}
+
+	param = memsize - (pram << 10);
+	printf("PARAM: @%08x\n", param);
+
+	memset((void*)param, 0, (pram << 10));
+	memcpy((void*)param, env_ptr, CFG_ENV_SIZE);
+
+	lptr = (ulong*)memsize;
+	*(--lptr) = CFG_ENV_SIZE;
+	*(--lptr) = pram << 10;
+	*(--lptr) = crc32(0, (void*)(memsize - 0x08), 0x08);
+	*(--lptr) = 0;
+	return 0;
+}
+U_BOOT_CMD(
+	painit,	1,	1,	do_painit,
+	"painit  - prepare PciAccess system\n",
+	NULL
+	);
+#endif /* CONFIG_PRAM */
+
+
+int do_selfreset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	if (argc > 1) {
+		if (argv[1][0] == '0') {
+			/* assert */
+			printf("self-reset# asserted\n");
+			out_be32((void*)GPIO0_TCR,
+				 in_be32((void*)GPIO0_TCR) | GPIO0_SELF_RST);
+		} else {
+			/* deassert */
+			printf("self-reset# deasserted\n");
+			out_be32((void*)GPIO0_TCR,
+				 in_be32((void*)GPIO0_TCR) & ~GPIO0_SELF_RST);
+		}
+	} else {
+		printf("self-reset# is %s\n",
+		       in_be32((void*)GPIO0_TCR) & GPIO0_SELF_RST ?
+		       "active" : "inactive");
+	}
+
+	return 0;
+}
+U_BOOT_CMD(
+	selfreset,	2,	1,	do_selfreset,
+	"selfreset- assert self-reset# signal\n",
+	NULL
+	);
+
+
+int do_resetout(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+	/* requiers bootet FPGA and PLD_IOEN_N active */
+	if (in_be32((void*)GPIO1_OR) & GPIO1_IOEN_N) {
+		printf("Error: resetout requires a bootet FPGA\n");
+		return -1;
+	}
+
+	if (argc > 1) {
+		if (argv[1][0] == '0') {
+			/* assert */
+			printf("PMC-RESETOUT# asserted\n");
+			FPGA_OUT32(&fpga->hostctrl,
+				   HOSTCTRL_PMCRSTOUT_GATE);
+		} else {
+			/* deassert */
+			printf("PMC-RESETOUT# deasserted\n");
+			FPGA_OUT32(&fpga->hostctrl,
+				   HOSTCTRL_PMCRSTOUT_GATE | HOSTCTRL_PMCRSTOUT_FLAG);
+		}
+	} else {
+		printf("PMC-RESETOUT# is %s\n",
+		       FPGA_IN32(&fpga->hostctrl) & HOSTCTRL_PMCRSTOUT_FLAG ?
+		       "inactive" : "active");
+	}
+
+	return 0;
+}
+U_BOOT_CMD(
+	resetout,	2,	1,	do_resetout,
+	"resetout - assert PMC-RESETOUT# signal\n",
+	NULL
+	);
+
+
+int do_inta(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	if (is_monarch()) {
+		printf("This command is only supported in non-monarch mode\n");
+		return -1;
+	}
+
+	if (argc > 1) {
+		if (argv[1][0] == '0') {
+			/* assert */
+			printf("inta# asserted\n");
+			out_be32((void*)GPIO1_TCR,
+				 in_be32((void*)GPIO1_TCR) | GPIO1_INTA_FAKE);
+		} else {
+			/* deassert */
+			printf("inta# deasserted\n");
+			out_be32((void*)GPIO1_TCR,
+				 in_be32((void*)GPIO1_TCR) & ~GPIO1_INTA_FAKE);
+		}
+	} else {
+		printf("inta# is %s\n", in_be32((void*)GPIO1_TCR) & GPIO1_INTA_FAKE ? "active" : "inactive");
+	}
+	return 0;
+}
+U_BOOT_CMD(
+	inta,	2,	1,	do_inta,
+	"inta    - Assert/Deassert or query INTA# state in non-monarch mode\n",
+	NULL
+	);
+
+
+/* test-only */
+int do_pmm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	ulong pciaddr;
+
+	if (argc > 1) {
+		pciaddr = simple_strtoul(argv[1], NULL, 16);
+
+		pciaddr &= 0xf0000000;
+
+		/* map PCI address at 0xc0000000 in PLB space */
+		out32r(PCIX0_PMM1MA, 0x00000000); /* PMM1 Mask/Attribute - disabled b4 setting */
+		out32r(PCIX0_PMM1LA, 0xc0000000); /* PMM1 Local Address */
+		out32r(PCIX0_PMM1PCILA, pciaddr); /* PMM1 PCI Low Address */
+		out32r(PCIX0_PMM1PCIHA, 0x00000000); /* PMM1 PCI High Address */
+		out32r(PCIX0_PMM1MA, 0xf0000001); /* 256MB + No prefetching, and enable region */
+	} else {
+		printf("Usage:\npmm %s\n", cmdtp->help);
+	}
+	return 0;
+}
+U_BOOT_CMD(
+	pmm,	2,	1,	do_pmm,
+	"pmm     - Setup pmm[1] registers\n",
+	"<pciaddr> (pciaddr will be aligned to 256MB)\n"
+	);
+
+#if defined(CFG_EEPROM_WREN)
+int do_eep_wren(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int query = argc == 1;
+	int state = 0;
+
+	if (query) {
+		/* Query write access state. */
+		state = eeprom_write_enable(CFG_I2C_EEPROM_ADDR, -1);
+		if (state < 0) {
+			puts("Query of write access state failed.\n");
+		} else {
+			printf("Write access for device 0x%0x is %sabled.\n",
+			       CFG_I2C_EEPROM_ADDR, state ? "en" : "dis");
+			state = 0;
+		}
+	} else {
+		if ('0' == argv[1][0]) {
+			/* Disable write access. */
+			state = eeprom_write_enable(CFG_I2C_EEPROM_ADDR, 0);
+		} else {
+			/* Enable write access. */
+			state = eeprom_write_enable(CFG_I2C_EEPROM_ADDR, 1);
+		}
+		if (state < 0) {
+			puts("Setup of write access state failed.\n");
+		}
+	}
+
+	return state;
+}
+U_BOOT_CMD(eepwren, 2, 0, do_eep_wren,
+	   "eepwren - Enable / disable / query EEPROM write access\n",
+	   NULL);
+#endif /* #if defined(CFG_EEPROM_WREN) */
+
+#endif /* CONFIG_CMD_BSP */
diff --git a/board/esd/pmc440/fpga.c b/board/esd/pmc440/fpga.c
new file mode 100644
index 0000000..85658f2
--- /dev/null
+++ b/board/esd/pmc440/fpga.c
@@ -0,0 +1,469 @@
+/*
+ * (C) Copyright 2007
+ * Matthias Fuchs, esd gmbh, matthias.fuchs@esd-electronics.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <spartan2.h>
+#include <spartan3.h>
+#include <command.h>
+#include "fpga.h"
+#include "pmc440.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_FPGA
+
+#if 0
+#define PMC440_FPGA_DEBUG
+#endif
+
+#ifdef PMC440_FPGA_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define	PRINTF(fmt,args...)
+#endif
+
+#define USE_SP_CODE
+
+#ifdef USE_SP_CODE
+Xilinx_Spartan3_Slave_Parallel_fns pmc440_fpga_fns = {
+	fpga_pre_config_fn,
+	fpga_pgm_fn,
+	fpga_init_fn,
+	NULL, /* err */
+	fpga_done_fn,
+	fpga_clk_fn,
+	fpga_cs_fn,
+	fpga_wr_fn,
+	NULL, /* rdata */
+	fpga_wdata_fn,
+	fpga_busy_fn,
+	fpga_abort_fn,
+	fpga_post_config_fn,
+};
+#else
+Xilinx_Spartan3_Slave_Serial_fns pmc440_fpga_fns = {
+	fpga_pre_config_fn,
+	fpga_pgm_fn,
+	fpga_clk_fn,
+	fpga_init_fn,
+	fpga_done_fn,
+	fpga_wr_fn,
+	fpga_post_config_fn,
+};
+#endif
+
+Xilinx_Spartan2_Slave_Serial_fns ngcc_fpga_fns = {
+	ngcc_fpga_pre_config_fn,
+	ngcc_fpga_pgm_fn,
+	ngcc_fpga_clk_fn,
+	ngcc_fpga_init_fn,
+	ngcc_fpga_done_fn,
+	ngcc_fpga_wr_fn,
+	ngcc_fpga_post_config_fn
+};
+
+Xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
+	XILINX_XC3S1200E_DESC(
+#ifdef USE_SP_CODE
+		slave_parallel,
+#else
+		slave_serial,
+#endif
+		(void *)&pmc440_fpga_fns,
+		0),
+	XILINX_XC2S200_DESC(
+		slave_serial,
+		(void *)&ngcc_fpga_fns,
+		0)
+};
+
+
+/*
+ * Set the active-low FPGA reset signal.
+ */
+void fpga_reset(int assert)
+{
+	PRINTF("%s:%d: RESET ", __FUNCTION__, __LINE__);
+	if (assert) {
+		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
+		PRINTF("asserted\n");
+	} else {
+		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
+		PRINTF("deasserted\n");
+	}
+}
+
+
+/*
+ * Initialize the SelectMap interface.  We assume that the mode and the
+ * initial state of all of the port pins have already been set!
+ */
+void fpga_serialslave_init(void)
+{
+	PRINTF ("%s:%d: Initialize serial slave interface\n", __FUNCTION__,
+		__LINE__);
+	fpga_pgm_fn(FALSE, FALSE, 0);	/* make sure program pin is inactive */
+}
+
+
+/*
+ * Set the FPGA's active-low SelectMap program line to the specified level
+ */
+int fpga_pgm_fn(int assert, int flush, int cookie)
+{
+	PRINTF("%s:%d: FPGA PROGRAM ",
+		__FUNCTION__, __LINE__);
+
+	if (assert) {
+		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_PRG);
+		PRINTF("asserted\n");
+	} else {
+		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_PRG);
+		PRINTF("deasserted\n");
+	}
+	return assert;
+}
+
+
+/*
+ * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
+ * asserted (low).
+ */
+int fpga_init_fn(int cookie)
+{
+	if (in_be32((void*)GPIO1_IR) & GPIO1_FPGA_INIT)
+		return 0;
+	else
+		return 1;
+}
+
+#ifdef USE_SP_CODE
+int fpga_abort_fn(int cookie)
+{
+	return 0;
+}
+
+
+int fpga_cs_fn(int assert_cs, int flush, int cookie)
+{
+	return assert_cs;
+}
+
+
+int fpga_busy_fn(int cookie)
+{
+	return 1;
+}
+#endif
+
+
+/*
+ * Test the state of the active-high FPGA DONE pin
+ */
+int fpga_done_fn(int cookie)
+{
+	if (in_be32((void*)GPIO1_IR) & GPIO1_FPGA_DONE)
+		return 1;
+	else
+		return 0;
+}
+
+
+/*
+ * FPGA pre-configuration function. Just make sure that
+ * FPGA reset is asserted to keep the FPGA from starting up after
+ * configuration.
+ */
+int fpga_pre_config_fn(int cookie)
+{
+	PRINTF("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
+	fpga_reset(TRUE);
+
+	/* release init# */
+	out_be32((void*)GPIO0_OR, in_be32((void*)GPIO0_OR) | GPIO0_FPGA_FORCEINIT);
+	/* disable PLD IOs */
+	out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_IOEN_N);
+	return 0;
+}
+
+
+/*
+ * FPGA post configuration function. Blip the FPGA reset line and then see if
+ * the FPGA appears to be running.
+ */
+int fpga_post_config_fn(int cookie)
+{
+	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+	int rc=0;
+	char *s;
+
+	PRINTF("%s:%d: FPGA post configuration\n", __FUNCTION__, __LINE__);
+
+	/* enable PLD0..7 pins */
+	out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_IOEN_N);
+
+	fpga_reset(TRUE);
+	udelay (100);
+	fpga_reset(FALSE);
+	udelay (100);
+
+	/* NGCC only: enable ledlink */
+	if ((s = getenv("bd_type")) && !strcmp(s, "ngcc"))
+		FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
+
+	return rc;
+}
+
+
+int fpga_clk_fn(int assert_clk, int flush, int cookie)
+{
+	if (assert_clk)
+		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_CLK);
+	else
+		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_CLK);
+
+	return assert_clk;
+}
+
+
+int fpga_wr_fn(int assert_write, int flush, int cookie)
+{
+	if (assert_write)
+		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
+	else
+		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
+
+	return assert_write;
+}
+
+#ifdef USE_SP_CODE
+int fpga_wdata_fn(uchar data, int flush, int cookie)
+{
+	uchar val = data;
+	ulong or = in_be32((void*)GPIO1_OR);
+	int i = 7;
+	do {
+		/* Write data */
+		if (val & 0x80)
+			or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
+		else
+			or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
+
+		out_be32((void*)GPIO1_OR, or);
+
+		/* Assert the clock */
+		or |= GPIO1_FPGA_CLK;
+		out_be32((void*)GPIO1_OR, or);
+		val <<= 1;
+		i --;
+	} while (i > 0);
+
+	/* Write last data bit (the 8th clock comes from the sp_load() code */
+	if (val & 0x80)
+		or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
+	else
+		or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
+
+	out_be32((void*)GPIO1_OR, or);
+
+	return 0;
+}
+#endif
+
+#define NGCC_FPGA_PRG  CLOCK_EN
+#define NGCC_FPGA_DATA RESET_OUT
+#define NGCC_FPGA_DONE CLOCK_IN
+#define NGCC_FPGA_INIT IRIGB_R_IN
+#define NGCC_FPGA_CLK  CLOCK_OUT
+
+void ngcc_fpga_serialslave_init(void)
+{
+	PRINTF("%s:%d: Initialize serial slave interface\n",
+		__FUNCTION__, __LINE__);
+
+	/* make sure program pin is inactive */
+	ngcc_fpga_pgm_fn (FALSE, FALSE, 0);
+}
+
+/*
+ * Set the active-low FPGA reset signal.
+ */
+void ngcc_fpga_reset(int assert)
+{
+	PRINTF("%s:%d: RESET ", __FUNCTION__, __LINE__);
+
+	if (assert) {
+		FPGA_CLRBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
+		PRINTF("asserted\n");
+	} else {
+		FPGA_SETBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
+		PRINTF("deasserted\n");
+	}
+}
+
+
+/*
+ * Set the FPGA's active-low SelectMap program line to the specified level
+ */
+int ngcc_fpga_pgm_fn(int assert, int flush, int cookie)
+{
+	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+	PRINTF("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__);
+
+	if (assert) {
+		FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_PRG);
+		PRINTF("asserted\n");
+	} else {
+		FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_PRG);
+		PRINTF("deasserted\n");
+	}
+
+	return assert;
+}
+
+
+/*
+ * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
+ * asserted (low).
+ */
+int ngcc_fpga_init_fn(int cookie)
+{
+	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+	PRINTF("%s:%d: INIT check... ", __FUNCTION__, __LINE__);
+	if (FPGA_IN32(&fpga->status) & NGCC_FPGA_INIT) {
+		PRINTF("high\n");
+		return 0;
+	} else {
+		PRINTF("low\n");
+		return 1;
+	}
+}
+
+
+/*
+ * Test the state of the active-high FPGA DONE pin
+ */
+int ngcc_fpga_done_fn(int cookie)
+{
+	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+	PRINTF("%s:%d: DONE check... ", __FUNCTION__, __LINE__);
+	if (FPGA_IN32(&fpga->status) & NGCC_FPGA_DONE) {
+		PRINTF("DONE high\n");
+		return 1;
+	} else {
+		PRINTF("low\n");
+		return 0;
+	}
+}
+
+
+/*
+ * FPGA pre-configuration function.
+ */
+int ngcc_fpga_pre_config_fn(int cookie)
+{
+	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+	PRINTF("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
+
+	ngcc_fpga_reset(TRUE);
+	FPGA_CLRBITS(&fpga->ctrla, 0xfffffe00);
+
+	ngcc_fpga_reset(TRUE);
+	return 0;
+}
+
+
+/*
+ * FPGA post configuration function. Blip the FPGA reset line and then see if
+ * the FPGA appears to be running.
+ */
+int ngcc_fpga_post_config_fn(int cookie)
+{
+	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+	PRINTF("%s:%d: NGCC FPGA post configuration\n", __FUNCTION__, __LINE__);
+
+	udelay (100);
+	ngcc_fpga_reset(FALSE);
+
+	FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
+
+	return 0;
+}
+
+
+int ngcc_fpga_clk_fn(int assert_clk, int flush, int cookie)
+{
+	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+	if (assert_clk)
+		FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_CLK);
+	else
+		FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_CLK);
+
+	return assert_clk;
+}
+
+
+int ngcc_fpga_wr_fn(int assert_write, int flush, int cookie)
+{
+	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+	if (assert_write)
+		FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_DATA);
+	else
+		FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_DATA);
+
+	return assert_write;
+}
+
+
+/*
+ * Initialize the fpga.  Return 1 on success, 0 on failure.
+ */
+int pmc440_init_fpga(void)
+{
+	char *s;
+
+	PRINTF("%s:%d: Initialize FPGA interface (relocation offset = 0x%.8lx)\n",
+		__FUNCTION__, __LINE__, gd->reloc_off);
+	fpga_init(gd->reloc_off);
+
+	fpga_serialslave_init ();
+	PRINTF("%s:%d: Adding fpga 0\n", __FUNCTION__, __LINE__);
+	fpga_add (fpga_xilinx, &fpga[0]);
+
+	/* NGCC only */
+	if ((s = getenv("bd_type")) && !strcmp(s, "ngcc")) {
+		ngcc_fpga_serialslave_init ();
+		PRINTF("%s:%d: Adding fpga 1\n", __FUNCTION__, __LINE__);
+		fpga_add (fpga_xilinx, &fpga[1]);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_FPGA */
diff --git a/board/esd/pmc440/fpga.h b/board/esd/pmc440/fpga.h
new file mode 100644
index 0000000..d61a3cf
--- /dev/null
+++ b/board/esd/pmc440/fpga.h
@@ -0,0 +1,47 @@
+/*
+ * (C) Copyright 2007
+ * Matthias Fuchs, esd gmbh germany, matthias.fuchs at esd-electronics.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+extern int pmc440_init_fpga(void);
+
+extern int fpga_pgm_fn(int assert_pgm, int flush, int cookie);
+extern int fpga_init_fn(int cookie);
+extern int fpga_err_fn(int cookie);
+extern int fpga_done_fn(int cookie);
+extern int fpga_clk_fn(int assert_clk, int flush, int cookie);
+extern int fpga_cs_fn(int assert_cs, int flush, int cookie);
+extern int fpga_wr_fn(int assert_write, int flush, int cookie);
+extern int fpga_wdata_fn (uchar data, int flush, int cookie);
+extern int fpga_read_data_fn(unsigned char *data, int cookie);
+extern int fpga_write_data_fn(unsigned char data, int flush, int cookie);
+extern int fpga_busy_fn(int cookie);
+extern int fpga_abort_fn(int cookie );
+extern int fpga_pre_config_fn(int cookie );
+extern int fpga_post_config_fn(int cookie );
+
+extern int ngcc_fpga_pgm_fn(int assert_pgm, int flush, int cookie);
+extern int ngcc_fpga_init_fn(int cookie);
+extern int ngcc_fpga_done_fn(int cookie);
+extern int ngcc_fpga_clk_fn(int assert_clk, int flush, int cookie);
+extern int ngcc_fpga_wr_fn(int assert_write, int flush, int cookie);
+extern int ngcc_fpga_pre_config_fn(int cookie );
+extern int ngcc_fpga_post_config_fn(int cookie );
-- 
1.5.3

  reply	other threads:[~2007-11-12 14:58 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <200711091606.07963.matthias.fuchs@esd-electronics.com>
2007-11-09 15:33 ` [U-Boot-Users] [PATCH 3/3] ppc4xx: Add initial esd PMC440 board support Stefan Roese
2007-11-11 12:04   ` Matthias Fuchs
2007-11-11 12:40     ` [U-Boot-Users] [PATCH 1/5] Add Epson RX8025 RTC support Matthias Fuchs
2007-11-11 12:40     ` [U-Boot-Users] [PATCH 2/5] serial: Make default_serial_console() a weak function Matthias Fuchs
2007-11-11 12:40     ` [U-Boot-Users] [PATCH 3/5] ppc4xx: Add initial esd PMC440 board files Matthias Fuchs
2007-11-11 12:40     ` [U-Boot-Users] [PATCH 4/5] ppc4xx: Add FPGA support and BSP command for PMC440 boards Matthias Fuchs
2007-11-12 14:58       ` Matthias Fuchs [this message]
2007-11-11 12:40     ` [U-Boot-Users] [PATCH 5/5] ppc4xx: Complete PMC440 board support Matthias Fuchs

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200711121558.12990.matthias.fuchs@esd-electronics.com \
    --to=matthias.fuchs@esd-electronics.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.