
From: Simon Glass <sjg@chromium.org> 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@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 49236db99c2..949ca42de94 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> @@ -485,6 +486,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 3c3545a2747..afcdf65ecbb 100644 --- a/arch/sandbox/include/asm/io.h +++ b/arch/sandbox/include/asm/io.h @@ -33,7 +33,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) sandbox_read((const void *)addr, SB_SIZE_8) diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index ff7f539965e..3aa35c112be 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; + enum { SB_MAX_BINDS = 4, }; @@ -68,6 +71,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 */ @@ -126,6 +192,7 @@ struct sandbox_state { const char *binds[SB_MAX_BINDS]; /* list of -B arguments */ int num_binds; /* number of -B arguments */ + struct alist mmio; /* list of struct sandbox_mmio */ /* * This struct is getting large. * -- 2.43.0