[PATCH] misc: fs_loader: Add QSPI RAW partition loading support
Jit Loon Lim
jit.loon.lim at intel.com
Fri Sep 2 08:43:27 CEST 2022
From: Tien Fong Chee <tien.fong.chee at intel.com>
Enhanced the generic firmware loader to support QSPI RAW partition
loading. This would enable FPGA configuration bitstream loading
from QSPI RAW partition to program FPGA.
Signed-off-by: Tien Fong Chee <tien.fong.chee at intel.com>
Signed-off-by: Jit Loon Lim <jit.loon.lim at intel.com>
---
drivers/misc/fs_loader.c | 92 ++++++++++++++++++++++++++++++++--------
include/fs_loader.h | 35 +++++++++++++++
2 files changed, 109 insertions(+), 18 deletions(-)
diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c
index 5b4d03639c..d57d717ed3 100644
--- a/drivers/misc/fs_loader.c
+++ b/drivers/misc/fs_loader.c
@@ -19,6 +19,7 @@
#include <mapmem.h>
#include <malloc.h>
#include <spl.h>
+#include <spi_flash.h>
#ifdef CONFIG_CMD_UBIFS
#include <ubi_uboot.h>
@@ -69,17 +70,18 @@ static int mount_ubifs(char *mtdpart, char *ubivol)
}
#endif
+__weak struct blk_desc *blk_get_by_device(struct udevice *dev)
+{
+ return NULL;
+}
+
static int select_fs_dev(struct device_plat *plat)
{
int ret;
-
if (plat->phandlepart.phandle) {
ofnode node;
-
node = ofnode_get_by_phandle(plat->phandlepart.phandle);
-
struct udevice *dev;
-
ret = device_get_global_by_ofnode(node, &dev);
if (!ret) {
struct blk_desc *desc = blk_get_by_device(dev);
@@ -95,16 +97,13 @@ static int select_fs_dev(struct device_plat *plat)
ret = mount_ubifs(plat->mtdpart, plat->ubivol);
if (ret)
return ret;
-
ret = fs_set_blk_dev("ubi", NULL, FS_TYPE_UBIFS);
} else {
debug("Error: unsupported storage device.\n");
return -ENODEV;
}
-
if (ret)
debug("Error: could not access storage.\n");
-
return ret;
}
@@ -123,16 +122,26 @@ static int _request_firmware_prepare(struct udevice *dev,
const char *name, void *dbuf,
size_t size, u32 offset)
{
- if (!name || name[0] == '\0')
- return -EINVAL;
-
struct firmware *firmwarep = dev_get_priv(dev);
+ struct device_plat *plat = dev_get_plat(dev);
+ char *endptr;
+ u32 fw_offset;
if (!firmwarep)
return -ENOMEM;
firmwarep->name = name;
- firmwarep->offset = offset;
+
+ if (plat->data_type == DATA_RAW) {
+ fw_offset = simple_strtoul(firmwarep->name, &endptr, 16);
+ if (firmwarep->name == endptr || *endptr != '\0')
+ return -EINVAL;
+
+ firmwarep->offset = fw_offset + offset;
+ } else {
+ firmwarep->offset = offset;
+ }
+
firmwarep->data = dbuf;
firmwarep->size = size;
@@ -149,7 +158,8 @@ static int fw_get_filesystem_firmware(struct udevice *dev)
{
loff_t actread;
char *storage_interface, *dev_part, *ubi_mtdpart, *ubi_volume;
- int ret;
+ int ret = 0;
+ struct device_plat *plat = dev_get_plat(dev);
storage_interface = env_get("storage_interface");
dev_part = env_get("fw_dev_part");
@@ -169,7 +179,8 @@ static int fw_get_filesystem_firmware(struct udevice *dev)
else
ret = -ENODEV;
} else {
- ret = select_fs_dev(dev_get_plat(dev));
+ if (plat->data_type == DATA_FS)
+ ret = select_fs_dev(dev_get_plat(dev));
}
if (ret)
@@ -180,8 +191,18 @@ static int fw_get_filesystem_firmware(struct udevice *dev)
if (!firmwarep)
return -ENOMEM;
- ret = fs_read(firmwarep->name, (ulong)map_to_sysmem(firmwarep->data),
- firmwarep->offset, firmwarep->size, &actread);
+ if (plat->data_type == DATA_FS)
+ ret = fs_read(firmwarep->name,
+ (ulong)map_to_sysmem(firmwarep->data),
+ firmwarep->offset, firmwarep->size, &actread);
+ else if (plat->data_type == DATA_RAW) {
+#ifdef CONFIG_SPI_FLASH
+ ret = spi_flash_read_dm(plat->flash, firmwarep->offset,
+ firmwarep->size,
+ (void *)map_to_sysmem(firmwarep->data));
+ actread = firmwarep->size;
+#endif
+ }
if (ret) {
debug("Error: %d Failed to read %s from flash %lld != %zu.\n",
@@ -230,6 +251,7 @@ int request_firmware_into_buf(struct udevice *dev,
static int fs_loader_of_to_plat(struct udevice *dev)
{
u32 phandlepart[2];
+ u32 sfconfig[4];
ofnode fs_loader_node = dev_ofnode(dev);
@@ -249,6 +271,17 @@ static int fs_loader_of_to_plat(struct udevice *dev)
plat->ubivol = (char *)ofnode_read_string(
fs_loader_node, "ubivol");
+
+ if (!ofnode_read_u32_array(fs_loader_node, "sfconfig", sfconfig,
+ 4)) {
+ plat->data_type = DATA_RAW;
+ plat->sfconfig.bus = sfconfig[0];
+ plat->sfconfig.cs = sfconfig[1];
+ plat->sfconfig.speed = sfconfig[2];
+ plat->sfconfig.mode = sfconfig[3];
+ } else {
+ plat->data_type = DATA_FS;
+ }
}
return 0;
@@ -256,10 +289,33 @@ static int fs_loader_of_to_plat(struct udevice *dev)
static int fs_loader_probe(struct udevice *dev)
{
-#if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(BLK)
- int ret;
+ int ret = 0;
struct device_plat *plat = dev_get_plat(dev);
+#ifdef CONFIG_SPI_FLASH
+ if (!plat->flash) {
+ debug("bus = %d\ncs = %d\nspeed= %d\nmode = %d\n",
+ plat->sfconfig.bus, plat->sfconfig.cs,
+ plat->sfconfig.speed, plat->sfconfig.mode);
+
+ ret = spi_flash_probe_bus_cs(plat->sfconfig.bus,
+ plat->sfconfig.cs,
+ plat->sfconfig.speed,
+ plat->sfconfig.mode,
+ &plat->flash);
+ if (ret) {
+ debug("fs_loader: Failed to initialize SPI flash at ");
+ debug("%u:%u (error %d)\n", plat->sfconfig.bus,
+ plat->sfconfig.cs, ret);
+ return -ENODEV;
+ }
+
+ if (!plat->flash)
+ return -EINVAL;
+ }
+#endif
+
+#if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(BLK)
if (plat->phandlepart.phandle) {
ofnode node = ofnode_get_by_phandle(plat->phandlepart.phandle);
struct udevice *parent_dev = NULL;
@@ -279,7 +335,7 @@ static int fs_loader_probe(struct udevice *dev)
}
#endif
- return 0;
+ return ret;
};
static const struct udevice_id fs_loader_ids[] = {
diff --git a/include/fs_loader.h b/include/fs_loader.h
index 8de7cb18dc..6b6450ac03 100644
--- a/include/fs_loader.h
+++ b/include/fs_loader.h
@@ -22,6 +22,35 @@ struct phandle_part {
u32 partition;
};
+/**
+ * struct sf_config - A place for storing serial flash configuration
+ *
+ * This holds information about bus, chip-select, and speed and mode of a serial
+ * flash configuration.
+ *
+ * @bus: SPI bus number.
+ * @cs: SPI chip selection.
+ * @speed: Speed selection.
+ * @mode: SPI mode.
+ */
+struct sf_config {
+ u32 bus;
+ u32 cs;
+ u32 speed;
+ u32 mode;
+};
+
+/**
+ * enum data_flags - Flag to indicate data as RAW or as filesystem
+ *
+ * DATA_RAW: Data stored as RAW.
+ * DATA_FS: DATA stored as filesystem.
+ */
+enum data_flags {
+ DATA_RAW, /* Stored in raw */
+ DATA_FS, /* Stored within a file system */
+};
+
/**
* struct phandle_part - A place for storing all supported storage devices
*
@@ -30,11 +59,17 @@ struct phandle_part {
* @phandlepart: Attribute data for block device.
* @mtdpart: MTD partition for ubi partition.
* @ubivol: UBI volume-name for ubifsmount.
+ * @enum data_flags: Data type (RAW or filesystem).
+ * @struct sf_config: Serial flash configuration.
+ * @struct spi_flash: Information about a SPI flash.
*/
struct device_plat {
struct phandle_part phandlepart;
char *mtdpart;
char *ubivol;
+ enum data_flags data_type;
+ struct sf_config sfconfig;
+ struct udevice *flash;
};
/**
--
2.26.2
More information about the U-Boot
mailing list