summaryrefslogtreecommitdiff
path: root/drivers/io
diff options
context:
space:
mode:
authorRuchika Gupta <ruchika.gupta@nxp.com>2018-06-27 12:18:22 +0530
committerRuchika Gupta <ruchika.gupta@nxp.com>2018-07-02 09:51:59 +0530
commitd4d598e92fe88ca3e60f41ff2f621aac176a02a6 (patch)
treed51ca812bb10f050be7ce3b74c33e74481e3c5f9 /drivers/io
parentf790cc0a9c492cf3615c82574e2c3f1ff8af0a3d (diff)
Extend FIP io driver to support multiple FIP devices
Platform can define MAX_NUM_FIP_DEVICES in platform_def.h to define the number of FIP io devices. The FIP driver doesn't support muliple open file. So only one single file can be open at a time across multiple FIP devices. For any FIP device, an image should be loaded fully before moving on to the next image. Signed-off-by: Ruchika Gupta <ruchika.gupta@nxp.com>
Diffstat (limited to 'drivers/io')
-rw-r--r--drivers/io/io_fip.c124
1 files changed, 114 insertions, 10 deletions
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index 17543390..6e7103db 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -19,6 +19,10 @@
#include <utils.h>
#include <uuid.h>
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES 1
+#endif
+
/* Useful for printing UUIDs when debugging.*/
#define PRINT_UUID2(x) \
"%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", \
@@ -32,11 +36,33 @@ typedef struct {
fip_toc_entry_t entry;
} file_state_t;
+/*
+ * Maintain dev_spec per FIP Device
+ * TODO - Add backend handles and file state
+ * per FIP device here once backends like io_memmap
+ * can support multiple open files
+ */
+typedef struct {
+ uintptr_t dev_spec;
+} fip_dev_state_t;
+
static const uuid_t uuid_null = { {0} };
+/*
+ * Only one file can be open across all FIP device
+ * as backends like io_memmap don't support
+ * multiple open files. The file state and
+ * backend handle should be maintained per FIP device
+ * if the same support is available in the backend
+ */
static file_state_t current_file = {0};
static uintptr_t backend_dev_handle;
static uintptr_t backend_image_spec;
+static fip_dev_state_t state_pool[MAX_FIP_DEVICES];
+static io_dev_info_t dev_info_pool[MAX_FIP_DEVICES];
+
+/* Track number of allocated fip devices */
+static unsigned int fip_dev_count;
/* Firmware Image Package driver functions */
static int fip_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
@@ -92,20 +118,94 @@ static const io_dev_funcs_t fip_dev_funcs = {
.dev_close = fip_dev_close,
};
+/* Locate a file state in the pool, specified by address */
+static int find_first_fip_state(const uintptr_t dev_spec,
+ unsigned int *index_out)
+{
+ int result = -ENOENT;
+ unsigned int index;
+
+ for (index = 0; index < (unsigned int)MAX_FIP_DEVICES; ++index) {
+ /* dev_spec is used as identifier since it's unique */
+ if (state_pool[index].dev_spec == dev_spec) {
+ result = 0;
+ *index_out = index;
+ break;
+ }
+ }
+ return result;
+}
+
-/* No state associated with this device so structure can be const */
-static const io_dev_info_t fip_dev_info = {
- .funcs = &fip_dev_funcs,
- .info = (uintptr_t)NULL
-};
+/* Allocate a device info from the pool and return a pointer to it */
+static int allocate_dev_info(io_dev_info_t **dev_info)
+{
+ int result = -ENOMEM;
+ assert(dev_info != NULL);
+
+ if (fip_dev_count < (unsigned int)MAX_FIP_DEVICES) {
+ unsigned int index = 0;
+
+ result = find_first_fip_state(0, &index);
+ assert(result == 0);
+ /* initialize dev_info */
+ dev_info_pool[index].funcs = &fip_dev_funcs;
+ dev_info_pool[index].info =
+ (uintptr_t)&state_pool[index];
+ *dev_info = &dev_info_pool[index];
+ ++fip_dev_count;
+ }
+
+ return result;
+}
-/* Open a connection to the FIP device */
-static int fip_dev_open(const uintptr_t dev_spec __unused,
+/* Release a device info to the pool */
+static int free_dev_info(io_dev_info_t *dev_info)
+{
+ int result;
+ unsigned int index = 0;
+ fip_dev_state_t *state;
+
+ assert(dev_info != NULL);
+
+ state = (fip_dev_state_t *)dev_info->info;
+ result = find_first_fip_state(state->dev_spec, &index);
+ if (result == 0) {
+ /* free if device info is valid */
+ zeromem(state, sizeof(fip_dev_state_t));
+ --fip_dev_count;
+ }
+
+ return result;
+}
+
+/*
+ * Multiple FIP devices can be opened depending on the value of
+ * MAX_FIP_DEVICES. Given that there is only one backend, only a
+ * single file can be open at a time by any FIP device.
+ */
+static int fip_dev_open(const uintptr_t dev_spec,
io_dev_info_t **dev_info)
{
+ int result;
+ io_dev_info_t *info;
+ fip_dev_state_t *state;
+
assert(dev_info != NULL);
- *dev_info = (io_dev_info_t *)&fip_dev_info; /* cast away const */
+#if MAX_FIP_DEVICES > 1
+ assert(dev_spec != (uintptr_t)NULL);
+#endif
+
+ result = allocate_dev_info(&info);
+ if (result != 0)
+ return -ENOMEM;
+
+ state = (fip_dev_state_t *)info->info;
+
+ state->dev_spec = dev_spec;
+
+ *dev_info = info;
return 0;
}
@@ -165,7 +265,7 @@ static int fip_dev_close(io_dev_info_t *dev_info)
backend_dev_handle = (uintptr_t)NULL;
backend_image_spec = (uintptr_t)NULL;
- return 0;
+ return free_dev_info(dev_info);
}
@@ -341,7 +441,11 @@ int register_io_dev_fip(const io_dev_connector_t **dev_con)
int result;
assert(dev_con != NULL);
- result = io_register_device(&fip_dev_info);
+ /*
+ * Since dev_info isn't really used in io_register_device, always
+ * use the same device info at here instead.
+ */
+ result = io_register_device(&dev_info_pool[0]);
if (result == 0)
*dev_con = &fip_dev_connector;