2 * drivers/staging/android/ion/rockchip/rockchip_ion.c
4 * Copyright (C) 2014 ROCKCHIP, Inc.
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
20 #include <linux/uaccess.h>
21 #include <linux/compat.h>
22 #include <linux/dma-buf.h>
23 #include <linux/dma-contiguous.h>
24 #include <linux/memblock.h>
25 #include <linux/of_fdt.h>
26 #include <linux/of_gpio.h>
27 #include <linux/rockchip_ion.h>
29 #include "../ion_priv.h"
31 struct ion_device *rockchip_ion_dev;
32 static struct ion_heap **heaps;
34 struct ion_heap_desc {
36 enum ion_heap_type type;
40 static struct ion_heap_desc ion_heap_meta[] = {
42 .id = ION_HEAP_TYPE_SYSTEM,
43 .type = ION_HEAP_TYPE_SYSTEM,
44 .name = "system-heap",
46 .id = ION_HEAP_TYPE_CARVEOUT,
47 .type = ION_HEAP_TYPE_CARVEOUT,
48 .name = "carveout-heap",
50 .id = ION_HEAP_TYPE_DMA,
51 .type = ION_HEAP_TYPE_DMA,
57 struct compat_ion_phys_data {
63 #define COMPAT_ION_IOC_GET_PHYS _IOWR(ION_IOC_ROCKCHIP_MAGIC, 0, \
64 struct compat_ion_phys_data)
66 static int compat_get_ion_phys_data(
67 struct compat_ion_phys_data __user *data32,
68 struct ion_phys_data __user *data)
74 err = get_user(i, &data32->handle);
75 err |= put_user(i, &data->handle);
76 err |= get_user(l, &data32->phys);
77 err |= put_user(l, &data->phys);
78 err |= get_user(l, &data32->size);
79 err |= put_user(l, &data->size);
84 static int compat_put_ion_phys_data(
85 struct compat_ion_phys_data __user *data32,
86 struct ion_phys_data __user *data)
92 err = get_user(i, &data->handle);
93 err |= put_user(i, &data32->handle);
94 err |= get_user(l, &data->phys);
95 err |= put_user(l, &data32->phys);
96 err |= get_user(l, &data->size);
97 err |= put_user(l, &data32->size);
103 static int rk_ion_get_phys(struct ion_client *client,
106 struct ion_phys_data data;
107 struct ion_handle *handle;
110 if (copy_from_user(&data, (void __user *)arg,
111 sizeof(struct ion_phys_data)))
114 handle = ion_handle_get_by_id(client, data.handle);
116 return PTR_ERR(handle);
118 ret = ion_phys(client, handle, &data.phys,
119 (size_t *)&data.size);
120 ion_handle_put(handle);
123 if (copy_to_user((void __user *)arg, &data,
124 sizeof(struct ion_phys_data)))
131 static int compat_rk_ion_get_phys(struct ion_client *client,
134 struct compat_ion_phys_data __user *data32;
135 struct ion_phys_data __user *data;
139 data32 = compat_ptr(arg);
140 data = compat_alloc_user_space(sizeof(*data));
144 err = compat_get_ion_phys_data(data32, data);
148 ret = rk_ion_get_phys(client, (unsigned long)data);
149 err = compat_put_ion_phys_data(data32, data);
151 return ret ? ret : err;
155 static long rk_custom_ioctl(struct ion_client *client,
163 case COMPAT_ION_IOC_GET_PHYS:
164 ret = compat_rk_ion_get_phys(client, arg);
167 case ION_IOC_GET_PHYS:
168 ret = rk_ion_get_phys(client, arg);
177 /* Return result of step for heap array. */
178 static int rk_ion_of_heap(struct ion_platform_heap *myheap,
179 struct device_node *node)
181 unsigned int reg[2] = {0,};
184 for (itype = 0; itype < ARRAY_SIZE(ion_heap_meta); itype++) {
185 if (strcmp(ion_heap_meta[itype].name, node->name))
188 myheap->name = node->name;
189 myheap->align = SZ_1M;
190 myheap->id = ion_heap_meta[itype].id;
191 if (!strcmp("cma-heap", node->name)) {
192 myheap->type = ION_HEAP_TYPE_DMA;
193 if (!of_property_read_u32_array(node, "reg", reg, 2)) {
194 myheap->base = reg[0];
195 myheap->size = reg[1];
200 if (!strcmp("system-heap", node->name)) {
201 myheap->type = ION_HEAP_TYPE_SYSTEM;
209 static struct ion_platform_data *rk_ion_of(struct device_node *node)
211 struct ion_platform_data *pdata;
213 struct device_node *child;
214 struct ion_platform_heap *myheap;
216 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
220 pdata->nr = of_get_child_count(node);
222 pdata->heaps = kcalloc(pdata->nr, sizeof(*myheap), GFP_KERNEL);
223 for_each_child_of_node(node, child) {
224 iheap += rk_ion_of_heap(&pdata->heaps[iheap], child);
227 if (pdata->nr != iheap) {
231 pr_err("%s: mismatch, repeating\n", __func__);
238 static int rk_ion_probe(struct platform_device *pdev)
242 struct ion_platform_data *pdata = pdev->dev.platform_data;
243 struct ion_device *idev;
246 pdata = rk_ion_of(pdev->dev.of_node);
247 pdev->dev.platform_data = pdata;
250 heaps = kcalloc(pdata->nr, sizeof(*heaps), GFP_KERNEL);
252 idev = ion_device_create(rk_custom_ioctl);
253 if (IS_ERR_OR_NULL(idev)) {
255 return PTR_ERR(idev);
258 rockchip_ion_dev = idev;
260 /* create the heaps as specified in the board file */
261 for (i = 0; i < pdata->nr; i++) {
262 struct ion_platform_heap *heap_data = &pdata->heaps[i];
264 heap_data->priv = &pdev->dev;
265 heaps[i] = ion_heap_create(heap_data);
266 if (IS_ERR_OR_NULL(heaps[i])) {
267 err = PTR_ERR(heaps[i]);
270 pr_info("rockchip ion: success to create - %s\n",
272 ion_device_add_heap(idev, heaps[i]);
274 platform_set_drvdata(pdev, idev);
278 for (i = 0; i < pdata->nr; i++) {
280 ion_heap_destroy(heaps[i]);
287 static int rk_ion_remove(struct platform_device *pdev)
289 struct ion_platform_data *pdata = pdev->dev.platform_data;
290 struct ion_device *idev = platform_get_drvdata(pdev);
293 ion_device_destroy(idev);
294 for (i = 0; i < pdata->nr; i++)
295 ion_heap_destroy(heaps[i]);
301 struct ion_client *rockchip_ion_client_create(const char *name)
303 if (!rockchip_ion_dev) {
304 pr_err("rockchip ion idev is NULL\n");
308 return ion_client_create(rockchip_ion_dev, name);
310 EXPORT_SYMBOL_GPL(rockchip_ion_client_create);
312 static const struct of_device_id rk_ion_match[] = {
313 { .compatible = "rockchip,ion", },
317 static struct platform_driver ion_driver = {
318 .probe = rk_ion_probe,
319 .remove = rk_ion_remove,
322 .owner = THIS_MODULE,
323 .of_match_table = of_match_ptr(rk_ion_match),
327 static int __init rk_ion_init(void)
329 return platform_driver_register(&ion_driver);
332 static void __exit rk_ion_exit(void)
334 platform_driver_unregister(&ion_driver);
337 subsys_initcall(rk_ion_init);
338 module_exit(rk_ion_exit);
340 MODULE_AUTHOR("Meiyou.chen <cmy@rock-chips.com>");
341 MODULE_DESCRIPTION("ROCKCHIP Ion driver");
342 MODULE_LICENSE("GPL v2");
343 MODULE_DEVICE_TABLE(of, rk_ion_match);