[PATCH v2 16/17] board: cssi: Load FPGA on MCR3000 board

Christophe Leroy
2024-04-15T06:10:43Z

Unlike CMPC885 and CMPCPRO boards, the FPGA of MCR3000 board doesn't
load code automatically but needs to be loaded by software through SPI.

Until now it was loaded later by Linux, but we'd like U-boot to have
access to some information that require the FPGA, like board address
in racks.

So, implemented the load of FPGA in U-boot.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
To avoid spamming your email boxes, the code isn't included in
the emailed patch but will be present in the PULL request
---
arch/powerpc/dts/mcr3000.dts | 6 ++++-
board/cssi/mcr3000/fpga_code.h | 10 +++++++
board/cssi/mcr3000/mcr3000.c | 48 ++++++++++++++++++++++++++++++++++
3 files changed, 63 insertions(+), 1 deletion(-)
create mode 100644 board/cssi/mcr3000/fpga_code.h

diff --git a/arch/powerpc/dts/mcr3000.dts b/arch/powerpc/dts/mcr3000.dts
index f678951e22..aa46007b8d 100644
--- a/arch/powerpc/dts/mcr3000.dts
+++ b/arch/powerpc/dts/mcr3000.dts
@@ -33,12 +33,16 @@
#size-cells = <0>;
cell-index = <0>;
compatible = "fsl,mpc8xx-spi";
- gpios = <&csspi 2 0>;
+ gpios = <&csspi 2 0
+ &csspi 0 0>;

temp@0 {
reg = <0>;
compatible = "ti,lm74";
};
+ fpga@1 {
+ reg = <1>;
+ };
};
};

diff --git a/board/cssi/mcr3000/fpga_code.h b/board/cssi/mcr3000/fpga_code.h
new file mode 100644
index 0000000000..0d710ba41f
--- /dev/null
+++ b/board/cssi/mcr3000/fpga_code.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2010 CS Systemes d'Information
+ *
+ * uCORE FPGA code for MCR3000 board
+ */
+
+u32 fpga_code[] = {
+ 0xdeadbeef,
+};
diff --git a/board/cssi/mcr3000/mcr3000.c b/board/cssi/mcr3000/mcr3000.c
index 537d7fa124..15a2d0d946 100644
--- a/board/cssi/mcr3000/mcr3000.c
+++ b/board/cssi/mcr3000/mcr3000.c
@@ -13,12 +13,15 @@
#include <mpc8xx.h>
#include <fdt_support.h>
#include <serial.h>
+#include <spi.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <dm/uclass.h>
#include <wdt.h>
#include <linux/delay.h>

+#include "fpga_code.h"
+
DECLARE_GLOBAL_DATA_PTR;

#define SDRAM_MAX_SIZE (32 * 1024 * 1024)
@@ -107,6 +110,49 @@ int dram_init(void)
return 0;
}

+static int load_fpga(void)
+{
+ immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ struct udevice *master;
+ struct spi_slave *slave;
+ int ret;
+
+ ret = uclass_get_device(UCLASS_SPI, 0, &master);
+ if (ret)
+ return ret;
+
+ ret = _spi_get_bus_and_cs(0, 1, 10000000, 0, "spi_generic_drv",
+ "generic_0:0", &master, &slave);
+ if (ret)
+ return ret;
+
+ ret = spi_claim_bus(slave);
+
+ printf("FPGA Init ... ");
+
+ clrbits_be32(&immr->im_cpm.cp_pbdat, 0x20000);
+ while ((in_be32(&immr->im_cpm.cp_pbdat) & 0x8000))
+ ;
+ setbits_be32(&immr->im_cpm.cp_pbdat, 0x20000);
+ while (!(in_be32(&immr->im_cpm.cp_pbdat) & 0x8000))
+ ;
+
+ printf("Loading ... ");
+
+ ret = spi_xfer(slave, sizeof(fpga_code) * BITS_PER_BYTE, fpga_code, NULL, 0);
+
+ spi_release_bus(slave);
+
+ if ((in_be32(&immr->im_cpm.cp_pbdat) & 0x4000)) {
+ printf("Done\n");
+ } else {
+ printf("FAILED\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
int misc_init_r(void)
{
immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
@@ -121,6 +167,8 @@ int misc_init_r(void)
setbits_be32(&immr->im_cpm.cp_pbdir, 0xf);
clrbits_be32(&immr->im_cpm.cp_pbdat, 0x1);

+ load_fpga();
+
/* if BTN_ACQ_AL is pressed then bootdelay is changed to 60 second */
if ((in_be16(&iop->iop_pcdat) & 0x0004) == 0)
env_set("bootdelay", "60");
--
2.43.0