drivers: of: add support for custom reserved memory drivers
authorMarek Szyprowski <m.szyprowski@samsung.com>
Fri, 28 Feb 2014 13:42:49 +0000 (14:42 +0100)
committerMark Brown <broonie@linaro.org>
Thu, 24 Jul 2014 18:57:03 +0000 (19:57 +0100)
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>
drivers/of/of_reserved_mem.c
include/asm-generic/vmlinux.lds.h
include/linux/of_reserved_mem.h

index 69b8117795850ad50f71fdb8301dbf42428d4eef..daaaf935911db2b670d443f72ade96f3875cf527 100644 (file)
@@ -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);
        }
 }
index eb58d2d7d9718d0c220387b3c60febf30f324e71..7414dd5132e5898f54b61913b8e5d38978c714f7 100644 (file)
 #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) = .;                                \
        CPU_DISCARD(init.rodata)                                        \
        MEM_DISCARD(init.rodata)                                        \
        CLK_OF_TABLES()                                                 \
+       RESERVEDMEM_OF_TABLES()                                         \
        CLKSRC_OF_TABLES()                                              \
        KERNEL_DTB()                                                    \
        IRQCHIP_OF_MATCH_TABLE()
index 89226ed7d954a2fd29b83b2db02f88f94014d407..9b1fbb7f29fc65a38782ecddd9282351a20c4a21 100644 (file)
@@ -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 */