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 <jo...@codeaurora.org>

Signed-off-by: Marek Szyprowski <m.szyprow...@samsung.com>
---
 drivers/of/of_reserved_mem.c      |   29 +++++++++++++++++++++++++++++
 include/asm-generic/vmlinux.lds.h |   11 +++++++++++
 include/linux/of_reserved_mem.h   |   33 +++++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+)

diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index c7ca6a4a42d1..97de6f882f85 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..f707176619a3 100644
--- a/include/linux/of_reserved_mem.h
+++ b/include/linux/of_reserved_mem.h
@@ -1,21 +1,54 @@
 #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,
+                              struct of_phandle_args *args);
+       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 */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to