[PATCH 03/13] sandbox: Support memory-mapped I/O
Simon Glass
sjg at chromium.org
Wed May 27 18:10:13 CEST 2026
Add a way for calls to readl()/writel() etc. to be picked up by a driver
in order to implement MMIO.
This works by registering some functions, which are then called when
accesses occur.
Add comments to sandbox_read() and sandbox_write() while we are here.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
arch/sandbox/cpu/mem.c | 49 +++++++++++++++++++++++
arch/sandbox/cpu/state.c | 2 +
arch/sandbox/include/asm/io.h | 15 +++++++
arch/sandbox/include/asm/state.h | 67 ++++++++++++++++++++++++++++++++
4 files changed, 133 insertions(+)
diff --git a/arch/sandbox/cpu/mem.c b/arch/sandbox/cpu/mem.c
index 54a55c1558c..010dc9c16a0 100644
--- a/arch/sandbox/cpu/mem.c
+++ b/arch/sandbox/cpu/mem.c
@@ -6,6 +6,7 @@
#define LOG_CATEGORY LOGC_SANDBOX
+#include <alist.h>
#include <errno.h>
#include <log.h>
#include <malloc.h>
@@ -231,9 +232,20 @@ void sandbox_map_list(void)
}
}
+static bool in_range(const struct sandbox_mmio *mmio, const void *addr)
+{
+ return addr >= mmio->base && addr < mmio->base + mmio->size;
+}
+
unsigned long sandbox_read(const void *addr, enum sandboxio_size_t size)
{
struct sandbox_state *state = state_get_current();
+ const struct sandbox_mmio *mmio;
+
+ alist_for_each(mmio, &state->mmio) {
+ if (in_range(mmio, addr))
+ return mmio->h_read(mmio->ctx, addr, size);
+ }
if (!state->allow_memio)
return 0;
@@ -255,6 +267,14 @@ unsigned long sandbox_read(const void *addr, enum sandboxio_size_t size)
void sandbox_write(void *addr, unsigned int val, enum sandboxio_size_t size)
{
struct sandbox_state *state = state_get_current();
+ const struct sandbox_mmio *mmio;
+
+ alist_for_each(mmio, &state->mmio) {
+ if (in_range(mmio, addr)) {
+ mmio->h_write(mmio->ctx, addr, val, size);
+ return;
+ }
+ }
if (!state->allow_memio)
return;
@@ -286,3 +306,32 @@ void sandbox_set_enable_pci_map(int enable)
{
enable_pci_map = enable;
}
+
+int sandbox_mmio_add(void *base, ulong size, sandbox_mmio_read_func h_read,
+ sandbox_mmio_write_func h_write, void *ctx)
+{
+ struct sandbox_state *state = state_get_current();
+ struct sandbox_mmio mmio;
+
+ mmio.base = base;
+ mmio.size = size;
+ mmio.h_read = h_read;
+ mmio.h_write = h_write;
+ mmio.ctx = ctx;
+ if (!alist_add(&state->mmio, mmio))
+ return -ENOMEM;
+
+ return 0;
+}
+
+void sandbox_mmio_remove(void *ctx)
+{
+ struct sandbox_state *state = state_get_current();
+ struct sandbox_mmio *from, *to;
+
+ alist_for_each_filter(from, to, &state->mmio) {
+ if (from->ctx != ctx)
+ *to++ = *from;
+ }
+ alist_update_end(&state->mmio, to);
+}
diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c
index 6a15c8b0a18..01742b63d05 100644
--- a/arch/sandbox/cpu/state.c
+++ b/arch/sandbox/cpu/state.c
@@ -3,6 +3,7 @@
* Copyright (c) 2011-2012 The Chromium OS Authors.
*/
+#include <alist.h>
#include <bloblist.h>
#include <config.h>
#include <errno.h>
@@ -487,6 +488,7 @@ int state_init(void)
printf("Out of memory\n");
os_exit(1);
}
+ alist_init_struct(&state->mmio, struct sandbox_mmio);
state_reset_for_test(state);
/*
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index e3034b9c703..99702532bc7 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -41,7 +41,22 @@ void unmap_physmem(const void *vaddr, unsigned long flags);
/* Map from a pointer to our RAM buffer */
phys_addr_t map_to_sysmem(const void *ptr);
+/**
+ * sandbox_read() - Perform a memory read
+ *
+ * @addr: Pointer to read from
+ * @size: Access size of read
+ * Return: Value obtained
+ */
unsigned long sandbox_read(const void *addr, enum sandboxio_size_t size);
+
+/**
+ * sandbox_write() - Perform a memory write
+ *
+ * @addr: Pointer to write to
+ * @val: Value to write
+ * @size: Access size of write
+ */
void sandbox_write(void *addr, unsigned int val, enum sandboxio_size_t size);
#define readb(addr) ({ u8 __v = sandbox_read((const void *)addr, SB_SIZE_8); __v; })
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 9dea0980bfc..582d8fa21a5 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -6,11 +6,14 @@
#ifndef __SANDBOX_STATE_H
#define __SANDBOX_STATE_H
+#include <alist.h>
#include <sysreset.h>
#include <stdbool.h>
#include <linux/list.h>
#include <linux/stringify.h>
+enum sandboxio_size_t;
+
/**
* Selects the behavior of the serial terminal.
*
@@ -64,6 +67,69 @@ struct sandbox_mapmem_entry {
struct list_head sibling_node;
};
+/**
+ * sandbox_read() - Read function for sandbox_mmio
+ *
+ * @addr: Pointer to read from
+ * @size: Access size of read
+ * Return: Value obtained
+ */
+typedef long (*sandbox_mmio_read_func)(void *ctx, const void *addr,
+ enum sandboxio_size_t size);
+
+/**
+ * sandbox_write() - Write function for sandbox_mmio
+ *
+ * @addr: Pointer to write to
+ * @val: Value to write
+ * @size: Access size of write
+ */
+typedef void (*sandbox_mmio_write_func)(void *ctx, void *addr, unsigned int val,
+ enum sandboxio_size_t size);
+
+/**
+ * sandbox_mmio_add() - Add a new MMIO region
+ *
+ * Register a new set of read/write functions to be called for a particular
+ * memory region
+ *
+ * @base: Base pointer for region
+ * @size: Size of region
+ * @h_read: Read handler
+ * @h_write: Write handler
+ * @ctx: Context pointer to passed to read/write functions
+ */
+int sandbox_mmio_add(void *base, ulong size, sandbox_mmio_read_func h_read,
+ sandbox_mmio_write_func h_write, void *ctx);
+
+/**
+ * sandbox_mmio_remove() - Remove an MMIO region
+ *
+ * All regions with the given @ctx are removed
+ *
+ * @ctx: Context to search for
+ */
+void sandbox_mmio_remove(void *ctx);
+
+/**
+ * struct sandbox_mmio - defines a region of memory-mapped I/O
+ *
+ * This allows accesses to a region of memory to go through provided functions
+ *
+ * @base: Base pointer of region
+ * @size: Size of region
+ * @h_read: Read handler
+ * @h_write: Write handler
+ * @ctx: Context pointer provided when registering
+ */
+struct sandbox_mmio {
+ void *base;
+ ulong size;
+ sandbox_mmio_read_func h_read;
+ sandbox_mmio_write_func h_write;
+ void *ctx;
+};
+
/* The complete state of the test system */
struct sandbox_state {
const char *cmd; /* Command to execute */
@@ -119,6 +185,7 @@ struct sandbox_state {
void *other_fdt_buf; /* 'other' FDT blob used by tests */
int other_size; /* size of other FDT blob */
+ struct alist mmio; /* list of struct sandbox_mmio */
/*
* This struct is getting large.
*
--
2.43.0
More information about the U-Boot
mailing list