[U-Boot] [PATCH 20/21] arm/km: enable BOCO2 FPGA download support

Holger Brunck holger.brunck at keymile.com
Wed Mar 21 16:49:39 CET 2012


From: Valentin Longchamp <valentin.longchamp at keymile.com>

This adds a first support of the FPGA download for a PCIe FPGA based
on the BOCO2 CPLD.

This takes place in 3 steps, all done accessing the SPICTRL reg of the
BOCO2:
1) start the FPGA config with an access to the FPGA_PROG bit
2) later in the boot sequence, wait for the FPGA_DONE bit to toggle to 1
   for the end of the FPGA configuration (with a timeout)
3) reset the FPGA
4) finally remove the access to its config EEPROM from the FPGA so that
   the CPU can update the FPGA configuration when the kernel is running

The boards with a PCIe FPGA but without BOCO2 still are supported.

The config option name is CONFIG_KM_FPGA_CONFIG

Signed-off-by: Valentin Longchamp <valentin.longchamp at keymile.com>
cc: Gerlando Falauto <gerlando.falauto at keymile.com>
cc: Prafulla Wadaskar <prafulla at marvell.com>
cc: Holger Brunck <holger.brunck at keymile.com>
---
 board/keymile/common/common.h      |    6 +
 board/keymile/km_arm/Makefile      |    4 +
 board/keymile/km_arm/fpga_config.c |  212 ++++++++++++++++++++++++++++++++++++
 board/keymile/km_arm/km_arm.c      |   21 +++-
 boards.cfg                         |    2 +-
 include/configs/km/km_arm.h        |    3 +
 include/configs/km_kirkwood.h      |    8 +-
 7 files changed, 246 insertions(+), 10 deletions(-)
 create mode 100644 board/keymile/km_arm/fpga_config.c

diff --git a/board/keymile/common/common.h b/board/keymile/common/common.h
index 49225b8..c58e565 100644
--- a/board/keymile/common/common.h
+++ b/board/keymile/common/common.h
@@ -131,6 +131,12 @@ int ext_switch_reg_write(const char *devname, u8 phy_addr, u8 port,
 int ext_switch_reg_read(const char *devname, u8 phy_addr, u8 port,
 	u8 reg, u16 *data);
 
+
+int trigger_fpga_config(void);
+int wait_for_fpga_config(void);
+int fpga_reset(void);
+int toggle_eeprom_spi_bus(void);
+
 int set_km_env(void);
 int fdt_set_node_and_value(void *blob,
 			char *nodename,
diff --git a/board/keymile/km_arm/Makefile b/board/keymile/km_arm/Makefile
index 06079e9..bd824e2 100644
--- a/board/keymile/km_arm/Makefile
+++ b/board/keymile/km_arm/Makefile
@@ -31,6 +31,10 @@ LIB	= $(obj)lib$(BOARD).o
 
 COBJS	:= $(BOARD).o ../common/common.o ../common/ivm.o
 
+ifdef CONFIG_KM_FPGA_CONFIG
+COBJS	+= fpga_config.o
+endif
+
 ifdef CONFIG_KM_MANAGED_SW_ADDR
 COBJS	+= managed_switch.o
 endif
diff --git a/board/keymile/km_arm/fpga_config.c b/board/keymile/km_arm/fpga_config.c
new file mode 100644
index 0000000..4356b9a
--- /dev/null
+++ b/board/keymile/km_arm/fpga_config.c
@@ -0,0 +1,212 @@
+/*
+ * (C) Copyright 2012
+ * Valentin Lontgchamp, Keymile AG, valentin.longchamp at keymile.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/errno.h>
+
+/* GPIO Pin from kirkwood connected to PROGRAM_B pin of the xilinx FPGA */
+#define KM_XLX_PROGRAM_B_PIN    39
+
+#define BOCO_ADDR	0x10
+
+#define ID_REG		0x00
+#define BOCO2_ID	0x5b
+
+static int check_boco2(void)
+{
+	int ret;
+	u8 id;
+
+	ret = i2c_read(BOCO_ADDR, ID_REG, 1, &id, 1);
+	if (ret) {
+		printf("%s: error reading the BOCO id !!\n", __func__);
+		return ret;
+	}
+
+	return (id == BOCO2_ID);
+}
+
+static int boco_clear_bits(u8 reg, u8 flags)
+{
+	int ret;
+	u8 regval;
+
+	/* give access to the EEPROM from FPGA */
+	ret = i2c_read(BOCO_ADDR, reg, 1, &regval, 1);
+	if (ret) {
+		printf("%s: error reading the BOCO @%#x !!\n",
+			__func__, reg);
+		return ret;
+	}
+	regval &= ~flags;
+	ret = i2c_write(BOCO_ADDR, reg, 1, &regval, 1);
+	if (ret) {
+		printf("%s: error writing the BOCO @%#x !!\n",
+			__func__, reg);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int boco_set_bits(u8 reg, u8 flags)
+{
+	int ret;
+	u8 regval;
+
+	/* give access to the EEPROM from FPGA */
+	ret = i2c_read(BOCO_ADDR, reg, 1, &regval, 1);
+	if (ret) {
+		printf("%s: error reading the BOCO @%#x !!\n",
+			__func__, reg);
+		return ret;
+	}
+	regval |= flags;
+	ret = i2c_write(BOCO_ADDR, reg, 1, &regval, 1);
+	if (ret) {
+		printf("%s: error writing the BOCO @%#x !!\n",
+			__func__, reg);
+		return ret;
+	}
+
+	return 0;
+}
+
+#define SPI_REG		0x06
+#define CFG_EEPROM	0x02
+#define FPGA_PROG	0x04
+#define FPGA_DONE	0x20
+
+int trigger_fpga_config(void)
+{
+	int ret = 0;
+
+	if (check_boco2()) {
+		/* we have a BOCO2, this has to be triggered here */
+
+		/* make sure the FPGA_can access the EEPROM */
+		ret = boco_clear_bits(SPI_REG, CFG_EEPROM);
+		if (ret)
+			return ret;
+
+		/* trigger the config start */
+		ret = boco_clear_bits(SPI_REG, FPGA_PROG);
+		if (ret)
+			return ret;
+
+		/* small delay for the pulse */
+		udelay(10);
+
+		/* up signal for pulse end */
+		ret = boco_set_bits(SPI_REG, FPGA_PROG);
+		if (ret)
+			return ret;
+
+	} else {
+		/* we do it the old way, with the gpio pin */
+		kw_gpio_set_valid(KM_XLX_PROGRAM_B_PIN, 1);
+		kw_gpio_direction_output(KM_XLX_PROGRAM_B_PIN, 0);
+		/* small delay for the pulse */
+		udelay(10);
+		kw_gpio_direction_input(KM_XLX_PROGRAM_B_PIN);
+	}
+
+	return 0;
+}
+
+int wait_for_fpga_config(void)
+{
+	int ret = 0;
+	u8 spictrl;
+	u32 timeout = 20000;
+
+	if (!check_boco2()) {
+		/* we do not have BOCO2, this is not really used */
+		return 0;
+	}
+
+	printf("PCIe FPGA config:");
+	do {
+		ret = i2c_read(BOCO_ADDR, SPI_REG, 1, &spictrl, 1);
+		if (ret) {
+			printf("%s: error reading the BOCO spictrl !!\n",
+				__func__);
+			return ret;
+		}
+		if (timeout-- == 0) {
+			printf(" FPGA_DONE timeout\n");
+			return -EFAULT;
+		}
+		udelay(10);
+	} while (!(spictrl & FPGA_DONE));
+
+	printf(" done\n");
+
+	return 0;
+}
+
+#define PRST1		0x4
+#define BRIDGE_RST	0x4
+
+int fpga_reset(void)
+{
+	int ret = 0;
+
+	if (!check_boco2()) {
+		/* we do not have BOCO2, this is not really used */
+		return 0;
+	}
+
+	ret = boco_clear_bits(PRST1, BRIDGE_RST);
+	if (ret)
+		return ret;
+
+	/* small delay for the pulse */
+	udelay(10);
+
+	ret = boco_set_bits(PRST1, BRIDGE_RST);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/* the FPGA was configured, we configure the BOCO2 so that the EEPROM
+ * is available from the Bobcat SPI bus */
+int toggle_eeprom_spi_bus(void)
+{
+	int ret = 0;
+
+	if (!check_boco2()) {
+		/* we do not have BOCO2, this is not really used */
+		return 0;
+	}
+
+	ret = boco_set_bits(SPI_REG, CFG_EEPROM);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
diff --git a/board/keymile/km_arm/km_arm.c b/board/keymile/km_arm/km_arm.c
index f4be40f..3857c7d 100644
--- a/board/keymile/km_arm/km_arm.c
+++ b/board/keymile/km_arm/km_arm.c
@@ -267,12 +267,6 @@ int board_early_init_f(void)
 	kw_gpio_set_valid(KM_KIRKWOOD_ENV_WP, 38);
 	kw_gpio_direction_output(KM_KIRKWOOD_ENV_WP, 1);
 #endif
-#if defined(CONFIG_KM_RECONFIG_XLX)
-	/* trigger the reconfiguration of the xilinx fpga */
-	kw_gpio_set_valid(KM_XLX_PROGRAM_B_PIN, 1);
-	kw_gpio_direction_output(KM_XLX_PROGRAM_B_PIN, 0);
-	kw_gpio_direction_input(KM_XLX_PROGRAM_B_PIN);
-#endif
 	return 0;
 }
 
@@ -281,6 +275,21 @@ int board_init(void)
 	/* address of boot parameters */
 	gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
 
+#if defined(CONFIG_KM_FPGA_CONFIG)
+	trigger_fpga_config();
+#endif
+
+	return 0;
+}
+
+int board_late_init(void)
+{
+#if defined(CONFIG_KM_FPGA_CONFIG)
+	wait_for_fpga_config();
+	fpga_reset();
+	toggle_eeprom_spi_bus();
+#endif
+
 	return 0;
 }
 
diff --git a/boards.cfg b/boards.cfg
index 4094494..a0ec17b 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -138,7 +138,7 @@ enbw_cmc                     arm         arm926ejs   enbw_cmc            enbw
 calimain                     arm         arm926ejs   calimain            omicron        davinci
 dns325                       arm         arm926ejs   -                   d-link         kirkwood
 km_kirkwood                  arm         arm926ejs   km_arm              keymile        kirkwood    km_kirkwood:KM_KIRKWOOD,KM_DISABLE_PCI
-km_kirkwood_pci              arm         arm926ejs   km_arm              keymile        kirkwood    km_kirkwood:KM_KIRKWOOD_PCI,KM_RECONFIG_XLX
+km_kirkwood_pci              arm         arm926ejs   km_arm              keymile        kirkwood    km_kirkwood:KM_KIRKWOOD_PCI,KM_FPGA_CONFIG
 kmnusa                       arm         arm926ejs   km_arm              keymile        kirkwood    km_kirkwood:KM_NUSA
 mgcoge3un                    arm         arm926ejs   km_arm              keymile        kirkwood    km_kirkwood:KM_MGCOGE3UN
 kmcoge5un                    arm         arm926ejs   km_arm              keymile        kirkwood    km_kirkwood:KMCOGE5UN
diff --git a/include/configs/km/km_arm.h b/include/configs/km/km_arm.h
index 5f05e8f..18b114f 100644
--- a/include/configs/km/km_arm.h
+++ b/include/configs/km/km_arm.h
@@ -306,4 +306,7 @@ int get_scl(void);
 #define CONFIG_POST_EXTERNAL_WORD_FUNCS
 #define CONFIG_CMD_DIAG
 
+/* we do the whole PCIe FPGA config stuff here */
+#define	BOARD_LATE_INIT
+
 #endif /* _CONFIG_KM_ARM_H */
diff --git a/include/configs/km_kirkwood.h b/include/configs/km_kirkwood.h
index 059fdbc..7d38413 100644
--- a/include/configs/km_kirkwood.h
+++ b/include/configs/km_kirkwood.h
@@ -175,10 +175,12 @@
 	MVGBE_SET_MII_SPEED_TO_100)
 #endif
 
-/* GPIO Pin from kirkwood connected to PROGRAM_B pin of the xilinx FPGA */
-#define KM_XLX_PROGRAM_B_PIN    39
-
 #ifdef CONFIG_KM_DISABLE_PCI
 #undef  CONFIG_KIRKWOOD_PCIE_INIT
 #endif
+
+#ifndef CONFIG_KM_FPGA_CONFIG
+#undef  BOARD_LATE_INIT
+#endif
+
 #endif /* _CONFIG_KM_KIRKWOOD */
-- 
1.7.1



More information about the U-Boot mailing list