aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2014-02-28 14:42:49 +0100
committerMark Brown <broonie@linaro.org>2014-08-12 12:42:54 +0100
commit61c2521e81afc2c2286f633e6130d0ffa2b93684 (patch)
tree6ab310a6125cc5c9129611d322317435164ebece
parente337f7e8b0fe7cec6a72fe6f5e3ac09c72b4152d (diff)
drivers: of: add support for custom reserved memory drivers
Add support for custom reserved memory drivers. Call their init() function for each reserved region and prepare for using operations provided by them with by the reserved_mem->ops array. Based on previous code provided by Josh Cartwright <joshc@codeaurora.org> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Grant Likely <grant.likely@linaro.org> (cherry picked from commit f618c4703a14672d27bc2ca5d132a844363d6f5f) Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--drivers/of/of_reserved_mem.c29
-rw-r--r--include/asm-generic/vmlinux.lds.h11
-rw-r--r--include/linux/of_reserved_mem.h32
3 files changed, 72 insertions, 0 deletions
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 69b811779585..daaaf935911d 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -170,6 +170,33 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
return 0;
}
+static const struct of_device_id __rmem_of_table_sentinel
+ __used __section(__reservedmem_of_table_end);
+
+/**
+ * res_mem_init_node() - call region specific reserved memory init code
+ */
+static int __init __reserved_mem_init_node(struct reserved_mem *rmem)
+{
+ extern const struct of_device_id __reservedmem_of_table[];
+ const struct of_device_id *i;
+
+ for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) {
+ reservedmem_of_init_fn initfn = i->data;
+ const char *compat = i->compatible;
+
+ if (!of_flat_dt_is_compatible(rmem->fdt_node, compat))
+ continue;
+
+ if (initfn(rmem, rmem->fdt_node, rmem->name) == 0) {
+ pr_info("Reserved memory: initialized node %s, compatible id %s\n",
+ rmem->name, compat);
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
/**
* fdt_init_reserved_mem - allocate and init all saved reserved memory regions
*/
@@ -184,5 +211,7 @@ void __init fdt_init_reserved_mem(void)
if (rmem->size == 0)
err = __reserved_mem_alloc_size(node, rmem->name,
&rmem->base, &rmem->size);
+ if (err == 0)
+ __reserved_mem_init_node(rmem);
}
}
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index bc2121fa9132..f10f64fcc815 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -167,6 +167,16 @@
#define CLK_OF_TABLES()
#endif
+#ifdef CONFIG_OF_RESERVED_MEM
+#define RESERVEDMEM_OF_TABLES() \
+ . = ALIGN(8); \
+ VMLINUX_SYMBOL(__reservedmem_of_table) = .; \
+ *(__reservedmem_of_table) \
+ *(__reservedmem_of_table_end)
+#else
+#define RESERVEDMEM_OF_TABLES()
+#endif
+
#define KERNEL_DTB() \
STRUCT_ALIGN(); \
VMLINUX_SYMBOL(__dtb_start) = .; \
@@ -490,6 +500,7 @@
TRACE_SYSCALLS() \
MEM_DISCARD(init.rodata) \
CLK_OF_TABLES() \
+ RESERVEDMEM_OF_TABLES() \
CLKSRC_OF_TABLES() \
KERNEL_DTB() \
IRQCHIP_OF_MATCH_TABLE()
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h
index 89226ed7d954..9b1fbb7f29fc 100644
--- a/include/linux/of_reserved_mem.h
+++ b/include/linux/of_reserved_mem.h
@@ -1,21 +1,53 @@
#ifndef __OF_RESERVED_MEM_H
#define __OF_RESERVED_MEM_H
+struct device;
+struct of_phandle_args;
+struct reserved_mem_ops;
+
struct reserved_mem {
const char *name;
unsigned long fdt_node;
+ const struct reserved_mem_ops *ops;
phys_addr_t base;
phys_addr_t size;
+ void *priv;
+};
+
+struct reserved_mem_ops {
+ void (*device_init)(struct reserved_mem *rmem,
+ struct device *dev);
+ void (*device_release)(struct reserved_mem *rmem,
+ struct device *dev);
};
+typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem,
+ unsigned long node, const char *uname);
+
#ifdef CONFIG_OF_RESERVED_MEM
void fdt_init_reserved_mem(void);
void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
phys_addr_t base, phys_addr_t size);
+
+#define RESERVEDMEM_OF_DECLARE(name, compat, init) \
+ static const struct of_device_id __reservedmem_of_table_##name \
+ __used __section(__reservedmem_of_table) \
+ = { .compatible = compat, \
+ .data = (init == (reservedmem_of_init_fn)NULL) ? \
+ init : init }
+
#else
static inline void fdt_init_reserved_mem(void) { }
static inline void fdt_reserved_mem_save_node(unsigned long node,
const char *uname, phys_addr_t base, phys_addr_t size) { }
+
+#define RESERVEDMEM_OF_DECLARE(name, compat, init) \
+ static const struct of_device_id __reservedmem_of_table_##name \
+ __attribute__((unused)) \
+ = { .compatible = compat, \
+ .data = (init == (reservedmem_of_init_fn)NULL) ? \
+ init : init }
+
#endif
#endif /* __OF_RESERVED_MEM_H */