gpu: ion: omap: Fix TILER secure heap base address
[android-sdk/kernel-video.git] / drivers / gpu / ion / omap / omap_ion.c
1 /*
2  * drivers/gpu/omap/omap_ion.c
3  *
4  * Copyright (C) 2011 Google, Inc.
5  *
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.
9  *
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.
14  *
15  */
17 #include <linux/err.h>
18 #include <linux/ion.h>
19 #include <linux/omap_ion.h>
20 #include <linux/platform_device.h>
21 #include <linux/slab.h>
22 #include <linux/uaccess.h>
23 #include "../ion_priv.h"
24 #include "omap_ion_priv.h"
25 #include <linux/module.h>
26 #include <linux/of.h>
29 struct ion_device *omap_ion_device;
30 EXPORT_SYMBOL(omap_ion_device);
32 static int num_heaps;
33 static struct ion_heap **heaps;
34 static struct ion_heap *tiler_heap;
35 static struct ion_heap *nonsecure_tiler_heap;
37 static struct ion_platform_data omap_ion_data = {
38         .nr = 5,
39         .heaps = {
40                 {
41                         .type = ION_HEAP_TYPE_CARVEOUT,
42                         .id = OMAP_ION_HEAP_SECURE_INPUT,
43                         .name = "secure_input",
44                 },
45                 {       .type = OMAP_ION_HEAP_TYPE_TILER,
46                         .id = OMAP_ION_HEAP_TILER,
47                         .name = "tiler",
48                 },
49                 {
50                         .type = OMAP_ION_HEAP_TYPE_TILER,
51                         .id = OMAP_ION_HEAP_NONSECURE_TILER,
52                         .name = "nonsecure_tiler",
53                 },
54                 {
55                         .type = ION_HEAP_TYPE_SYSTEM,
56                         .id = OMAP_ION_HEAP_SYSTEM,
57                         .name = "system",
58                 },
59                 {
60                         .type = OMAP_ION_HEAP_TYPE_TILER_RESERVATION,
61                         .id = OMAP_ION_HEAP_TILER_RESERVATION,
62                         .name = "tiler_reservation",
63                 },
64         },
65 };
68 int omap_ion_tiler_alloc(struct ion_client *client,
69                          struct omap_ion_tiler_alloc_data *data)
70 {
71         return omap_tiler_alloc(tiler_heap, client, data);
72 }
73 EXPORT_SYMBOL(omap_ion_tiler_alloc);
75 int omap_ion_nonsecure_tiler_alloc(struct ion_client *client,
76                          struct omap_ion_tiler_alloc_data *data)
77 {
78         if (!nonsecure_tiler_heap)
79                 return -ENOMEM;
80         return omap_tiler_alloc(nonsecure_tiler_heap, client, data);
81 }
82 EXPORT_SYMBOL(omap_ion_nonsecure_tiler_alloc);
84 static long omap_ion_ioctl(struct ion_client *client, unsigned int cmd,
85                     unsigned long arg)
86 {
87         switch (cmd) {
88         case OMAP_ION_TILER_ALLOC:
89         {
90                 struct omap_ion_tiler_alloc_data data;
91                 int ret;
93                 if (!tiler_heap) {
94                         pr_err("%s: Tiler heap requested but no tiler heap "
95                                         "exists on this platform\n", __func__);
96                         return -EINVAL;
97                 }
98                 if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
99                         return -EFAULT;
100                 ret = omap_ion_tiler_alloc(client, &data);
101                 if (ret)
102                         return ret;
103                 if (copy_to_user((void __user *)arg, &data,
104                                  sizeof(data)))
105                         return -EFAULT;
106                 break;
107         }
108         default:
109                 pr_err("%s: Unknown custom ioctl\n", __func__);
110                 return -ENOTTY;
111         }
112         return 0;
115 static int omap_ion_probe(struct platform_device *pdev)
117         int err;
118         int i;
119         struct device_node *node = pdev->dev.of_node;
120         uint omap_ion_heap_secure_input_base = 0;
121         uint omap_ion_heap_tiler_base = 0;
122         uint omap_ion_heap_nonsecure_tiler_base = 0;
123         uint omap_ion_heap_secure_input_size = 0;
124         uint omap_ion_heap_tiler_size = 0;
125         uint omap_ion_heap_nonsecure_tiler_size = 0;
126         
127         omap_ion_device = ion_device_create(omap_ion_ioctl);
128         if (IS_ERR_OR_NULL(omap_ion_device)) {
129                 kfree(heaps);
130                 return PTR_ERR(omap_ion_device);
131         }
133         if (node) {
134                 of_property_read_u32(node, "ti,omap_ion_heap_secure_input_base",
135                                      &omap_ion_heap_secure_input_base);
136                 of_property_read_u32(node, "ti,omap_ion_heap_tiler_base",
137                                      &omap_ion_heap_tiler_base);
138                 of_property_read_u32(node, "ti,omap_ion_heap_nonsecure_tiler_base",
139                                      &omap_ion_heap_nonsecure_tiler_base);
141                 of_property_read_u32(node, "ti,omap_ion_heap_secure_input_size",
142                                      &omap_ion_heap_secure_input_size);
143                 of_property_read_u32(node, "ti,omap_ion_heap_tiler_size",
144                                      &omap_ion_heap_tiler_size);
145                 of_property_read_u32(node, "ti,omap_ion_heap_nonsecure_tiler_size",
146                                      &omap_ion_heap_nonsecure_tiler_size);
147         }
149         num_heaps = omap_ion_data.nr;
151         heaps = kzalloc(sizeof(struct ion_heap *)*num_heaps, GFP_KERNEL);
152         
154         for (i = 0; i < num_heaps; i++) {
155                 struct ion_platform_heap *heap_data = &omap_ion_data.heaps[i];
156                 if (heap_data->type == (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER) {
157                         if (heap_data->id == OMAP_ION_HEAP_NONSECURE_TILER) {
158                                 heap_data->base = omap_ion_heap_nonsecure_tiler_base;
159                                 heap_data->size = omap_ion_heap_nonsecure_tiler_size;
160                         } else {
161                                 heap_data->base = omap_ion_heap_tiler_base;
162                                 heap_data->size = omap_ion_heap_tiler_size;
163                         }
164                 } else if (heap_data->type ==
165                                 ION_HEAP_TYPE_CARVEOUT && heap_data->id == OMAP_ION_HEAP_SECURE_INPUT) {
166                         heap_data->base = omap_ion_heap_secure_input_base;
167                         heap_data->size = omap_ion_heap_secure_input_size;
168                 }
169         }
171         /* create the heaps as specified in the board file */
172         for (i = 0; i < num_heaps; i++) {
173                 struct ion_platform_heap *heap_data = &omap_ion_data.heaps[i];
174                 if (heap_data->type == (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER) {
175                         heaps[i] = omap_tiler_heap_create(heap_data);
176                         if (heap_data->id == OMAP_ION_HEAP_NONSECURE_TILER)
177                                 nonsecure_tiler_heap = heaps[i];
178                         else
179                                 tiler_heap = heaps[i];
180                 } else if (heap_data->type ==
181                                 (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER_RESERVATION) {
182                         heaps[i] = omap_tiler_heap_create(heap_data);
183                 } else {
184                         heap_data->size = omap_ion_heap_secure_input_size;
185                         heaps[i] = ion_heap_create(heap_data);
186                 }
187                 if (IS_ERR_OR_NULL(heaps[i])) {
188                         err = PTR_ERR(heaps[i]);
189                         goto err;
190                 }
191                 ion_device_add_heap(omap_ion_device, heaps[i]);
192                 pr_info("%s: adding heap %s of type %d with %lx@%x\n",
193                         __func__, heap_data->name, heap_data->type,
194                         heap_data->base, heap_data->size);
196         }
198         platform_set_drvdata(pdev, omap_ion_device);
199         return 0;
200 err:
201         for (i = 0; i < num_heaps; i++) {
202                 if (heaps[i]) {
203                         if (heaps[i]->type == (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER)
204                                 omap_tiler_heap_destroy(heaps[i]);
205                         else
206                                 ion_heap_destroy(heaps[i]);
207                 }
208         }
209         kfree(heaps);
210         return err;
213 static int omap_ion_remove(struct platform_device *pdev)
215         struct ion_device *idev = platform_get_drvdata(pdev);
216         int i;
218         ion_device_destroy(idev);
219         for (i = 0; i < num_heaps; i++)
220                 if (heaps[i]->type == (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER)
221                         omap_tiler_heap_destroy(heaps[i]);
222                 else
223                         ion_heap_destroy(heaps[i]);
224         kfree(heaps);
225         return 0;
228 static void (*export_fd_to_ion_handles)(int fd,
229                 struct ion_client **client,
230                 struct ion_handle **handles,
231                 int *num_handles);
233 void omap_ion_register_pvr_export(void *pvr_export_fd)
235         export_fd_to_ion_handles = pvr_export_fd;
237 EXPORT_SYMBOL(omap_ion_register_pvr_export);
239 int omap_ion_share_fd_to_buffers(int fd, struct ion_buffer **buffers,
240                 int *num_handles)
242         struct ion_handle **handles;
243         struct ion_client *client;
244         int i = 0, ret = 0;
246         handles = kzalloc(*num_handles * sizeof(struct ion_handle *),
247                           GFP_KERNEL);
248         if (!handles)
249                 return -ENOMEM;
251         if (export_fd_to_ion_handles) {
252                 export_fd_to_ion_handles(fd,
253                                 &client,
254                                 handles,
255                                 num_handles);
256         } else {
257                 pr_err("%s: export_fd_to_ion_handles not initialized",
258                                 __func__);
259                 ret = -EINVAL;
260                 goto exit;
261         }
263         for (i = 0; i < *num_handles; i++) {
264                 if (handles[i])
265                         buffers[i] = ion_share_dma_buf(client, handles[i]);
266         }
268 exit:
269         kfree(handles);
270         return ret;
272 EXPORT_SYMBOL(omap_ion_share_fd_to_buffers);
274 static const struct of_device_id omap_ion_of_match[] = {
275         {.compatible = "ti,ion-omap", },
276         { },
277 };
280 static struct platform_driver ion_driver = {
281         .probe = omap_ion_probe,
282         .remove = omap_ion_remove,
283         .driver = { .name = "ion-omap",
284                                 .of_match_table = omap_ion_of_match
285         }
286 };
288 static int __init ion_init(void)
290         return platform_driver_register(&ion_driver);
293 static void __exit ion_exit(void)
295         platform_driver_unregister(&ion_driver);
298 module_init(ion_init);
299 module_exit(ion_exit);