Browse Source

arm/km: skip FPGA config when already configured

In order to be able to perform board resets without interrupting the
traffic, the configuration of an already properly configured FPGA is
skipped.

This is because some PCIe FPGAs embed some other function that must
continue to work over reset.

It is then the responsibility of the application to trigger a
reconfiguration when needed. This is done by lowering the FPGA_INIT_B
pin for delaying the configuration to u-boot @ next reboot, and then
lower the FPGA_PROGRAM_B signal.

Signed-off-by: Valentin Longchamp <valentin.longchamp@keymile.com>
Valentin Longchamp 13 years ago
parent
commit
bcac5b1b2c
1 changed files with 40 additions and 1 deletions
  1. 40 1
      board/keymile/km_arm/fpga_config.c

+ 40 - 1
board/keymile/km_arm/fpga_config.c

@@ -96,12 +96,43 @@ static int boco_set_bits(u8 reg, u8 flags)
 #define SPI_REG		0x06
 #define SPI_REG		0x06
 #define CFG_EEPROM	0x02
 #define CFG_EEPROM	0x02
 #define FPGA_PROG	0x04
 #define FPGA_PROG	0x04
+#define FPGA_INIT_B	0x10
 #define FPGA_DONE	0x20
 #define FPGA_DONE	0x20
 
 
+static int fpga_done()
+{
+	int ret = 0;
+	u8 regval;
+
+	/* this is only supported with the boco2 design */
+	if (!check_boco2())
+		return 0;
+
+	ret = i2c_read(BOCO_ADDR, SPI_REG, 1, &regval, 1);
+	if (ret) {
+		printf("%s: error reading the BOCO @%#x !!\n",
+			__func__, SPI_REG);
+		return 0;
+	}
+
+	return regval & FPGA_DONE ? 1 : 0;
+}
+
+int skip;
+
 int trigger_fpga_config(void)
 int trigger_fpga_config(void)
 {
 {
 	int ret = 0;
 	int ret = 0;
 
 
+	/* if the FPGA is already configured, we do not want to
+	 * reconfigure it */
+	skip = 0;
+	if (fpga_done()) {
+		printf("PCIe FPGA config: skipped\n");
+		skip = 1;
+		return 0;
+	}
+
 	if (check_boco2()) {
 	if (check_boco2()) {
 		/* we have a BOCO2, this has to be triggered here */
 		/* we have a BOCO2, this has to be triggered here */
 
 
@@ -111,7 +142,7 @@ int trigger_fpga_config(void)
 			return ret;
 			return ret;
 
 
 		/* trigger the config start */
 		/* trigger the config start */
-		ret = boco_clear_bits(SPI_REG, FPGA_PROG);
+		ret = boco_clear_bits(SPI_REG, FPGA_PROG | FPGA_INIT_B);
 		if (ret)
 		if (ret)
 			return ret;
 			return ret;
 
 
@@ -123,6 +154,11 @@ int trigger_fpga_config(void)
 		if (ret)
 		if (ret)
 			return ret;
 			return ret;
 
 
+		/* finally, raise INIT_B to remove the config delay */
+		ret = boco_set_bits(SPI_REG, FPGA_INIT_B);
+		if (ret)
+			return ret;
+
 	} else {
 	} else {
 		/* we do it the old way, with the gpio pin */
 		/* we do it the old way, with the gpio pin */
 		kw_gpio_set_valid(KM_XLX_PROGRAM_B_PIN, 1);
 		kw_gpio_set_valid(KM_XLX_PROGRAM_B_PIN, 1);
@@ -141,6 +177,9 @@ int wait_for_fpga_config(void)
 	u8 spictrl;
 	u8 spictrl;
 	u32 timeout = 20000;
 	u32 timeout = 20000;
 
 
+	if (skip)
+		return 0;
+
 	if (!check_boco2()) {
 	if (!check_boco2()) {
 		/* we do not have BOCO2, this is not really used */
 		/* we do not have BOCO2, this is not really used */
 		return 0;
 		return 0;