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 static struct ion_device *idev;
36 static struct ion_heap **heaps;
38 struct ion_heap_desc {
40 enum ion_heap_type type;
44 extern struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
46 extern int ion_handle_put(struct ion_handle *handle);
48 #define ION_CMA_HEAP_NAME "cma"
49 #define ION_IOMMU_HEAP_NAME "iommu"
50 #define ION_VMALLOC_HEAP_NAME "vmalloc"
51 #define ION_DRM_HEAP_NAME "drm"
52 #define ION_CARVEOUT_HEAP_NAME "carveout"
54 #define MAX_ION_HEAP 10
56 static struct ion_platform_heap ion_plat_heap[MAX_ION_HEAP];
57 struct ion_platform_data ion_pdata = {
59 .heaps = ion_plat_heap,
62 static struct ion_heap_desc ion_heap_meta[] = {
64 .id = ION_VMALLOC_HEAP_ID,
65 .type = ION_HEAP_TYPE_SYSTEM,
66 .name = ION_VMALLOC_HEAP_NAME,
69 .id = ION_CMA_HEAP_ID,
70 .type = ION_HEAP_TYPE_DMA,
71 .name = ION_CMA_HEAP_NAME,
74 .id = ION_DRM_HEAP_ID,
75 .type = ION_HEAP_TYPE_DRM,
76 .name = ION_DRM_HEAP_NAME,
79 .id = ION_CARVEOUT_HEAP_ID,
80 .type = ION_HEAP_TYPE_CARVEOUT,
81 .name = ION_CARVEOUT_HEAP_NAME,
85 struct device rockchip_ion_cma_dev = {
86 .coherent_dma_mask = DMA_BIT_MASK(32),
87 .init_name = "rockchip_ion_cma",
90 static int rockchip_ion_populate_heap(struct ion_platform_heap *heap)
94 unsigned int len = ARRAY_SIZE(ion_heap_meta);
95 for (i = 0; i < len; ++i) {
96 if (ion_heap_meta[i].id == heap->id) {
97 heap->name = ion_heap_meta[i].name;
98 heap->type = ion_heap_meta[i].type;
99 if(heap->id == ION_CMA_HEAP_ID)
100 heap->priv = &rockchip_ion_cma_dev;
106 pr_err("%s: Unable to populate heap, error: %d", __func__, ret);
110 struct ion_client *rockchip_ion_client_create(const char *name)
112 return ion_client_create(idev, name);
114 EXPORT_SYMBOL(rockchip_ion_client_create);
116 static long rockchip_custom_ioctl (struct ion_client *client, unsigned int cmd,
119 pr_debug("[%s %d] cmd=%X\n", __func__, __LINE__, cmd);
122 case ION_IOC_GET_PHYS:
124 struct ion_phys_data data;
125 struct ion_handle *handle;
128 if (copy_from_user(&data, (void __user *)arg,
129 sizeof(struct ion_phys_data)))
132 handle = ion_handle_get_by_id(client, data.handle);
134 return PTR_ERR(handle);
136 ret = ion_phys(client, handle, &data.phys, (size_t *)&data.size);
137 pr_debug("ret=%d, phys=0x%lX\n", ret, data.phys);
138 ion_handle_put(handle);
141 if (copy_to_user((void __user *)arg, &data, sizeof(struct ion_phys_data)))
152 static int rockchip_ion_probe(struct platform_device *pdev)
154 struct ion_platform_data *pdata;
158 err = device_register(&rockchip_ion_cma_dev);
160 pr_err("Could not register %s\n", dev_name(&rockchip_ion_cma_dev));
164 if (pdev->dev.of_node) {
167 return PTR_ERR(pdata);
170 pdata = pdev->dev.platform_data;
173 num_heaps = pdata->nr;
174 heaps = kzalloc(sizeof(struct ion_heap *) * num_heaps, GFP_KERNEL);
176 idev = ion_device_create(rockchip_custom_ioctl);
177 if (IS_ERR_OR_NULL(idev)) {
179 return PTR_ERR(idev);
181 /* create the heaps as specified in the board file */
182 for (i = 0; i < num_heaps; i++) {
183 struct ion_platform_heap *heap_data = &pdata->heaps[i];
185 heaps[i] = ion_heap_create(heap_data);
186 if (IS_ERR_OR_NULL(heaps[i])) {
187 err = PTR_ERR(heaps[i]);
190 ion_device_add_heap(idev, heaps[i]);
192 platform_set_drvdata(pdev, idev);
194 pr_info("Rockchip ion module is successfully loaded (%s)\n", ROCKCHIP_ION_VERSION);
197 for (i = 0; i < num_heaps; i++) {
199 ion_heap_destroy(heaps[i]);
205 static int rockchip_ion_remove(struct platform_device *pdev)
207 struct ion_device *idev = platform_get_drvdata(pdev);
210 ion_device_destroy(idev);
211 for (i = 0; i < num_heaps; i++)
212 ion_heap_destroy(heaps[i]);
217 int __init rockchip_ion_find_heap(unsigned long node, const char *uname,
218 int depth, void *data)
222 struct ion_platform_heap* heap;
223 struct ion_platform_data* pdata = (struct ion_platform_data*)data;
225 if (pdata==NULL || pdata->nr >= MAX_ION_HEAP) {
227 pr_err("ion heap is too much!\n");
231 if (!of_flat_dt_is_compatible(node, "rockchip,ion-heap"))
234 prop = of_get_flat_dt_prop(node, "rockchip,ion_heap", &len);
235 if (!prop || (len != sizeof(__be32)))
238 heap = &pdata->heaps[pdata->nr++];
239 heap->base = heap->size = heap->align = 0;
240 heap->id = be32_to_cpu(prop[0]);
241 rockchip_ion_populate_heap(heap);
243 prop = of_get_flat_dt_prop(node, "reg", &len);
244 if (prop && (len >= 2*sizeof(__be32))) {
245 heap->base = be32_to_cpu(prop[0]);
246 heap->size = be32_to_cpu(prop[1]);
247 if (len==3*sizeof(__be32))
248 heap->align = be32_to_cpu(prop[2]);
251 pr_info("ion heap(%s): base(%lx) size(%zx) align(%lx)\n", heap->name,
252 heap->base, heap->size, heap->align);
256 static const struct of_device_id rockchip_ion_dt_ids[] = {
257 { .compatible = "rockchip,ion", },
261 static struct platform_driver ion_driver = {
262 .probe = rockchip_ion_probe,
263 .remove = rockchip_ion_remove,
265 .name = "ion-rockchip",
266 .owner = THIS_MODULE,
267 .of_match_table = of_match_ptr(rockchip_ion_dt_ids),
271 static int __init ion_init(void)
273 return platform_driver_register(&ion_driver);
276 static void __exit ion_exit(void)
278 platform_driver_unregister(&ion_driver);
281 subsys_initcall(ion_init);
282 module_exit(ion_exit);