diff options
| -rw-r--r-- | drivers/of/of_reserved_mem.c | 70 | ||||
| -rw-r--r-- | include/linux/of_reserved_mem.h | 7 |
2 files changed, 77 insertions, 0 deletions
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 632aae861375..59fb12e84e6b 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c | |||
| @@ -206,8 +206,16 @@ void __init fdt_init_reserved_mem(void) | |||
| 206 | for (i = 0; i < reserved_mem_count; i++) { | 206 | for (i = 0; i < reserved_mem_count; i++) { |
| 207 | struct reserved_mem *rmem = &reserved_mem[i]; | 207 | struct reserved_mem *rmem = &reserved_mem[i]; |
| 208 | unsigned long node = rmem->fdt_node; | 208 | unsigned long node = rmem->fdt_node; |
| 209 | int len; | ||
| 210 | const __be32 *prop; | ||
| 209 | int err = 0; | 211 | int err = 0; |
| 210 | 212 | ||
| 213 | prop = of_get_flat_dt_prop(node, "phandle", &len); | ||
| 214 | if (!prop) | ||
| 215 | prop = of_get_flat_dt_prop(node, "linux,phandle", &len); | ||
| 216 | if (prop) | ||
| 217 | rmem->phandle = of_read_number(prop, len/4); | ||
| 218 | |||
| 211 | if (rmem->size == 0) | 219 | if (rmem->size == 0) |
| 212 | err = __reserved_mem_alloc_size(node, rmem->name, | 220 | err = __reserved_mem_alloc_size(node, rmem->name, |
| 213 | &rmem->base, &rmem->size); | 221 | &rmem->base, &rmem->size); |
| @@ -215,3 +223,65 @@ void __init fdt_init_reserved_mem(void) | |||
| 215 | __reserved_mem_init_node(rmem); | 223 | __reserved_mem_init_node(rmem); |
| 216 | } | 224 | } |
| 217 | } | 225 | } |
| 226 | |||
| 227 | static inline struct reserved_mem *__find_rmem(struct device_node *node) | ||
| 228 | { | ||
| 229 | unsigned int i; | ||
| 230 | |||
| 231 | if (!node->phandle) | ||
| 232 | return NULL; | ||
| 233 | |||
| 234 | for (i = 0; i < reserved_mem_count; i++) | ||
| 235 | if (reserved_mem[i].phandle == node->phandle) | ||
| 236 | return &reserved_mem[i]; | ||
| 237 | return NULL; | ||
| 238 | } | ||
| 239 | |||
| 240 | /** | ||
| 241 | * of_reserved_mem_device_init() - assign reserved memory region to given device | ||
| 242 | * | ||
| 243 | * This function assign memory region pointed by "memory-region" device tree | ||
| 244 | * property to the given device. | ||
| 245 | */ | ||
| 246 | void of_reserved_mem_device_init(struct device *dev) | ||
| 247 | { | ||
| 248 | struct reserved_mem *rmem; | ||
| 249 | struct device_node *np; | ||
| 250 | |||
| 251 | np = of_parse_phandle(dev->of_node, "memory-region", 0); | ||
| 252 | if (!np) | ||
| 253 | return; | ||
| 254 | |||
| 255 | rmem = __find_rmem(np); | ||
| 256 | of_node_put(np); | ||
| 257 | |||
| 258 | if (!rmem || !rmem->ops || !rmem->ops->device_init) | ||
| 259 | return; | ||
| 260 | |||
| 261 | rmem->ops->device_init(rmem, dev); | ||
| 262 | dev_info(dev, "assigned reserved memory node %s\n", rmem->name); | ||
| 263 | } | ||
| 264 | |||
| 265 | /** | ||
| 266 | * of_reserved_mem_device_release() - release reserved memory device structures | ||
| 267 | * | ||
| 268 | * This function releases structures allocated for memory region handling for | ||
| 269 | * the given device. | ||
| 270 | */ | ||
| 271 | void of_reserved_mem_device_release(struct device *dev) | ||
| 272 | { | ||
| 273 | struct reserved_mem *rmem; | ||
| 274 | struct device_node *np; | ||
| 275 | |||
| 276 | np = of_parse_phandle(dev->of_node, "memory-region", 0); | ||
| 277 | if (!np) | ||
| 278 | return; | ||
| 279 | |||
| 280 | rmem = __find_rmem(np); | ||
| 281 | of_node_put(np); | ||
| 282 | |||
| 283 | if (!rmem || !rmem->ops || !rmem->ops->device_release) | ||
| 284 | return; | ||
| 285 | |||
| 286 | rmem->ops->device_release(rmem, dev); | ||
| 287 | } | ||
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h index 4669ddfdd5af..5b5efae09135 100644 --- a/include/linux/of_reserved_mem.h +++ b/include/linux/of_reserved_mem.h | |||
| @@ -8,6 +8,7 @@ struct reserved_mem_ops; | |||
| 8 | struct reserved_mem { | 8 | struct reserved_mem { |
| 9 | const char *name; | 9 | const char *name; |
| 10 | unsigned long fdt_node; | 10 | unsigned long fdt_node; |
| 11 | unsigned long phandle; | ||
| 11 | const struct reserved_mem_ops *ops; | 12 | const struct reserved_mem_ops *ops; |
| 12 | phys_addr_t base; | 13 | phys_addr_t base; |
| 13 | phys_addr_t size; | 14 | phys_addr_t size; |
| @@ -27,10 +28,16 @@ typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem); | |||
| 27 | _OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn) | 28 | _OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn) |
| 28 | 29 | ||
| 29 | #ifdef CONFIG_OF_RESERVED_MEM | 30 | #ifdef CONFIG_OF_RESERVED_MEM |
| 31 | void of_reserved_mem_device_init(struct device *dev); | ||
| 32 | void of_reserved_mem_device_release(struct device *dev); | ||
| 33 | |||
| 30 | void fdt_init_reserved_mem(void); | 34 | void fdt_init_reserved_mem(void); |
| 31 | void fdt_reserved_mem_save_node(unsigned long node, const char *uname, | 35 | void fdt_reserved_mem_save_node(unsigned long node, const char *uname, |
| 32 | phys_addr_t base, phys_addr_t size); | 36 | phys_addr_t base, phys_addr_t size); |
| 33 | #else | 37 | #else |
| 38 | static inline void of_reserved_mem_device_init(struct device *dev) { } | ||
| 39 | static inline void of_reserved_mem_device_release(struct device *pdev) { } | ||
| 40 | |||
| 34 | static inline void fdt_init_reserved_mem(void) { } | 41 | static inline void fdt_init_reserved_mem(void) { } |
| 35 | static inline void fdt_reserved_mem_save_node(unsigned long node, | 42 | static inline void fdt_reserved_mem_save_node(unsigned long node, |
| 36 | const char *uname, phys_addr_t base, phys_addr_t size) { } | 43 | const char *uname, phys_addr_t base, phys_addr_t size) { } |
