Merge remote-tracking branch 'staging/staging-next'
[deliverable/linux.git] / drivers / staging / android / ion / ion_of.c
CommitLineData
13439479
LA
1/*
2 * Based on work from:
3 * Andrew Andrianov <andrew@ncrmnt.org>
4 * Google
5 * The Linux Foundation
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/init.h>
13#include <linux/platform_device.h>
14#include <linux/slab.h>
15#include <linux/of.h>
16#include <linux/of_platform.h>
17#include <linux/of_address.h>
18#include <linux/clk.h>
19#include <linux/dma-mapping.h>
20#include <linux/cma.h>
21#include <linux/dma-contiguous.h>
22#include <linux/io.h>
23#include <linux/of_reserved_mem.h>
24#include "ion.h"
25#include "ion_priv.h"
26#include "ion_of.h"
27
28int ion_parse_dt_heap_common(struct device_node *heap_node,
29 struct ion_platform_heap *heap,
30 struct ion_of_heap *compatible)
31{
32 int i;
33
34 for (i = 0; compatible[i].name != NULL; i++) {
35 if (of_device_is_compatible(heap_node, compatible[i].compat))
36 break;
37 }
38
39 if (compatible[i].name == NULL)
40 return -ENODEV;
41
42 heap->id = compatible[i].heap_id;
43 heap->type = compatible[i].type;
44 heap->name = compatible[i].name;
45 heap->align = compatible[i].align;
46
47 /* Some kind of callback function pointer? */
48
49 pr_info("%s: id %d type %d name %s align %lx\n", __func__,
50 heap->id, heap->type, heap->name, heap->align);
51 return 0;
52}
53
54int ion_setup_heap_common(struct platform_device *parent,
55 struct device_node *heap_node,
56 struct ion_platform_heap *heap)
57{
58 int ret = 0;
59
60 switch (heap->type) {
61 case ION_HEAP_TYPE_CARVEOUT:
62 case ION_HEAP_TYPE_CHUNK:
63 if (heap->base && heap->size)
64 return 0;
65
66 ret = of_reserved_mem_device_init(heap->priv);
67 break;
68 default:
69 break;
70 }
71
72 return ret;
73}
74
75struct ion_platform_data *ion_parse_dt(struct platform_device *pdev,
76 struct ion_of_heap *compatible)
77{
78 int num_heaps, ret;
79 const struct device_node *dt_node = pdev->dev.of_node;
80 struct device_node *node;
81 struct ion_platform_heap *heaps;
82 struct ion_platform_data *data;
83 int i = 0;
84
85 num_heaps = of_get_available_child_count(dt_node);
86
87 if (!num_heaps)
88 return ERR_PTR(-EINVAL);
89
90 heaps = devm_kzalloc(&pdev->dev,
91 sizeof(struct ion_platform_heap)*num_heaps,
92 GFP_KERNEL);
93 if (!heaps)
94 return ERR_PTR(-ENOMEM);
95
96 data = devm_kzalloc(&pdev->dev, sizeof(struct ion_platform_data),
97 GFP_KERNEL);
98 if (!data)
99 return ERR_PTR(-ENOMEM);
100
101 for_each_available_child_of_node(dt_node, node) {
102 struct platform_device *heap_pdev;
103
104 ret = ion_parse_dt_heap_common(node, &heaps[i], compatible);
105 if (ret)
106 return ERR_PTR(ret);
107
108 heap_pdev = of_platform_device_create(node, heaps[i].name,
109 &pdev->dev);
110 if (!pdev)
111 return ERR_PTR(-ENOMEM);
112 heap_pdev->dev.platform_data = &heaps[i];
113
114 heaps[i].priv = &heap_pdev->dev;
115
116 ret = ion_setup_heap_common(pdev, node, &heaps[i]);
117 if (ret)
118 goto out_err;
119 i++;
120 }
121
122
123 data->heaps = heaps;
124 data->nr = num_heaps;
125 return data;
126
127out_err:
128 for ( ; i >= 0; i--)
129 if (heaps[i].priv)
130 of_device_unregister(to_platform_device(heaps[i].priv));
131
132 return ERR_PTR(ret);
133}
134
135void ion_destroy_platform_data(struct ion_platform_data *data)
136{
137 int i;
138
139 for (i = 0; i < data->nr; i++)
140 if (data->heaps[i].priv)
141 of_device_unregister(to_platform_device(
142 data->heaps[i].priv));
143}
144
145#ifdef CONFIG_OF_RESERVED_MEM
146#include <linux/of.h>
147#include <linux/of_fdt.h>
148#include <linux/of_reserved_mem.h>
149
150static int rmem_ion_device_init(struct reserved_mem *rmem, struct device *dev)
151{
152 struct platform_device *pdev = to_platform_device(dev);
153 struct ion_platform_heap *heap = pdev->dev.platform_data;
154
155 heap->base = rmem->base;
156 heap->base = rmem->size;
157 pr_debug("%s: heap %s base %pa size %pa dev %p\n", __func__,
158 heap->name, &rmem->base, &rmem->size, dev);
159 return 0;
160}
161
162static void rmem_ion_device_release(struct reserved_mem *rmem,
163 struct device *dev)
164{
165 return;
166}
167
168static const struct reserved_mem_ops rmem_dma_ops = {
169 .device_init = rmem_ion_device_init,
170 .device_release = rmem_ion_device_release,
171};
172
173static int __init rmem_ion_setup(struct reserved_mem *rmem)
174{
175 phys_addr_t size = rmem->size;
176
177 size = size / 1024;
178
179 pr_info("Ion memory setup at %pa size %pa MiB\n",
180 &rmem->base, &size);
181 rmem->ops = &rmem_dma_ops;
182 return 0;
183}
184RESERVEDMEM_OF_DECLARE(ion, "ion-region", rmem_ion_setup);
185#endif
This page took 0.032675 seconds and 5 git commands to generate.