2 * drivers/gpu/rockchip/rockchip_ion.c
4 * Copyright (C) 2011 Google, 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/err.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
20 #include <linux/rockchip_ion.h>
21 #include <linux/uaccess.h>
22 #include "../ion_priv.h"
23 #include <linux/dma-buf.h>
24 #include <linux/dma-contiguous.h>
25 #include <linux/memblock.h>
29 #include <linux/of_gpio.h>
30 #include <video/of_display_timing.h>
31 #include <linux/of_fdt.h>
34 struct ion_device *rockchip_ion_dev;
35 EXPORT_SYMBOL(rockchip_ion_dev);
38 static struct ion_heap **heaps;
40 struct ion_heap_desc {
42 enum ion_heap_type type;
46 extern struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
48 extern int ion_handle_put(struct ion_handle *handle);
50 #define ION_CMA_HEAP_NAME "cma"
51 #define ION_IOMMU_HEAP_NAME "iommu"
52 #define ION_VMALLOC_HEAP_NAME "vmalloc"
53 #define ION_DRM_HEAP_NAME "drm"
54 #define ION_CARVEOUT_HEAP_NAME "carveout"
56 #define MAX_ION_HEAP 10
58 static struct ion_platform_heap ion_plat_heap[MAX_ION_HEAP];
59 struct ion_platform_data ion_pdata = {
61 .heaps = ion_plat_heap,
64 static struct ion_heap_desc ion_heap_meta[] = {
66 .id = ION_VMALLOC_HEAP_ID,
67 .type = ION_HEAP_TYPE_SYSTEM,
68 .name = ION_VMALLOC_HEAP_NAME,
71 .id = ION_CMA_HEAP_ID,
72 .type = ION_HEAP_TYPE_DMA,
73 .name = ION_CMA_HEAP_NAME,
76 .id = ION_DRM_HEAP_ID,
77 .type = ION_HEAP_TYPE_DRM,
78 .name = ION_DRM_HEAP_NAME,
81 .id = ION_CARVEOUT_HEAP_ID,
82 .type = ION_HEAP_TYPE_CARVEOUT,
83 .name = ION_CARVEOUT_HEAP_NAME,
87 struct device rockchip_ion_cma_dev = {
88 .coherent_dma_mask = DMA_BIT_MASK(32),
89 .init_name = "rockchip_ion_cma",
92 static int rockchip_ion_populate_heap(struct ion_platform_heap *heap)
96 unsigned int len = ARRAY_SIZE(ion_heap_meta);
97 for (i = 0; i < len; ++i) {
98 if (ion_heap_meta[i].id == heap->id) {
99 heap->name = ion_heap_meta[i].name;
100 heap->type = ion_heap_meta[i].type;
101 if(heap->id == ION_CMA_HEAP_ID)
102 heap->priv = &rockchip_ion_cma_dev;
108 pr_err("%s: Unable to populate heap, error: %d", __func__, ret);
112 struct ion_client *rockchip_ion_client_create(const char *name)
114 return ion_client_create(rockchip_ion_dev, name);
116 EXPORT_SYMBOL(rockchip_ion_client_create);
118 static long rockchip_custom_ioctl (struct ion_client *client, unsigned int cmd,
121 pr_debug("[%s %d] cmd=%X\n", __func__, __LINE__, cmd);
124 case ION_IOC_GET_PHYS:
126 struct ion_phys_data data;
127 struct ion_handle *handle;
130 if (copy_from_user(&data, (void __user *)arg,
131 sizeof(struct ion_phys_data)))
134 handle = ion_handle_get_by_id(client, data.handle);
136 return PTR_ERR(handle);
138 ret = ion_phys(client, handle, &data.phys, (size_t *)&data.size);
139 pr_debug("ret=%d, phys=0x%lX\n", ret, data.phys);
140 ion_handle_put(handle);
143 if (copy_to_user((void __user *)arg, &data, sizeof(struct ion_phys_data)))
154 static int rockchip_ion_probe(struct platform_device *pdev)
156 struct ion_platform_data *pdata;
157 struct ion_device *idev;
161 err = device_register(&rockchip_ion_cma_dev);
163 pr_err("Could not register %s\n", dev_name(&rockchip_ion_cma_dev));
167 if (pdev->dev.of_node) {
170 return PTR_ERR(pdata);
173 pdata = pdev->dev.platform_data;
176 num_heaps = pdata->nr;
177 heaps = kzalloc(sizeof(struct ion_heap *) * num_heaps, GFP_KERNEL);
179 idev = ion_device_create(rockchip_custom_ioctl);
180 if (IS_ERR_OR_NULL(idev)) {
182 return PTR_ERR(idev);
184 rockchip_ion_dev = idev;
185 /* create the heaps as specified in the board file */
186 for (i = 0; i < num_heaps; i++) {
187 struct ion_platform_heap *heap_data = &pdata->heaps[i];
189 heaps[i] = ion_heap_create(heap_data);
190 if (IS_ERR_OR_NULL(heaps[i])) {
191 err = PTR_ERR(heaps[i]);
194 ion_device_add_heap(idev, heaps[i]);
196 platform_set_drvdata(pdev, idev);
198 pr_info("Rockchip ion module is successfully loaded (%s)\n", ROCKCHIP_ION_VERSION);
201 for (i = 0; i < num_heaps; i++) {
203 ion_heap_destroy(heaps[i]);
209 static int rockchip_ion_remove(struct platform_device *pdev)
211 struct ion_device *idev = platform_get_drvdata(pdev);
214 ion_device_destroy(idev);
215 for (i = 0; i < num_heaps; i++)
216 ion_heap_destroy(heaps[i]);
221 int __init rockchip_ion_find_heap(unsigned long node, const char *uname,
222 int depth, void *data)
226 struct ion_platform_heap* heap;
227 struct ion_platform_data* pdata = (struct ion_platform_data*)data;
229 if (pdata==NULL || pdata->nr >= MAX_ION_HEAP) {
231 pr_err("ion heap is too much!\n");
235 if (!of_flat_dt_is_compatible(node, "rockchip,ion-heap"))
238 prop = of_get_flat_dt_prop(node, "rockchip,ion_heap", &len);
239 if (!prop || (len != sizeof(__be32)))
242 heap = &pdata->heaps[pdata->nr++];
243 heap->base = heap->size = heap->align = 0;
244 heap->id = be32_to_cpu(prop[0]);
245 rockchip_ion_populate_heap(heap);
247 prop = of_get_flat_dt_prop(node, "reg", &len);
248 if (prop && (len >= 2*sizeof(__be32))) {
249 heap->base = be32_to_cpu(prop[0]);
250 heap->size = be32_to_cpu(prop[1]);
251 if (len==3*sizeof(__be32))
252 heap->align = be32_to_cpu(prop[2]);
255 pr_info("ion heap(%s): base(%lx) size(%zx) align(%lx)\n", heap->name,
256 heap->base, heap->size, heap->align);
260 static const struct of_device_id rockchip_ion_dt_ids[] = {
261 { .compatible = "rockchip,ion", },
265 static struct platform_driver ion_driver = {
266 .probe = rockchip_ion_probe,
267 .remove = rockchip_ion_remove,
269 .name = "ion-rockchip",
270 .owner = THIS_MODULE,
271 .of_match_table = of_match_ptr(rockchip_ion_dt_ids),
275 static int __init ion_init(void)
277 return platform_driver_register(&ion_driver);
280 static void __exit ion_exit(void)
282 platform_driver_unregister(&ion_driver);
285 subsys_initcall(ion_init);
286 module_exit(ion_exit);