ion_dummy_driver.c revision d320c455cb726cc0618ad9852982debc8af535b3
1/*
2 * drivers/gpu/ion/ion_dummy_driver.c
3 *
4 * Copyright (C) 2013 Linaro, 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 */
16
17#include <linux/err.h>
18#include <linux/platform_device.h>
19#include <linux/slab.h>
20#include <linux/init.h>
21#include <linux/bootmem.h>
22#include <linux/memblock.h>
23#include <linux/sizes.h>
24#include <linux/io.h>
25#include "ion.h"
26#include "ion_priv.h"
27
28static struct ion_device *idev;
29static struct ion_heap **heaps;
30
31static void *carveout_ptr;
32static void *chunk_ptr;
33
34static struct ion_platform_heap dummy_heaps[] = {
35		{
36			.id	= ION_HEAP_TYPE_SYSTEM,
37			.type	= ION_HEAP_TYPE_SYSTEM,
38			.name	= "system",
39		},
40		{
41			.id	= ION_HEAP_TYPE_SYSTEM_CONTIG,
42			.type	= ION_HEAP_TYPE_SYSTEM_CONTIG,
43			.name	= "system contig",
44		},
45		{
46			.id	= ION_HEAP_TYPE_CARVEOUT,
47			.type	= ION_HEAP_TYPE_CARVEOUT,
48			.name	= "carveout",
49			.size	= SZ_4M,
50		},
51		{
52			.id	= ION_HEAP_TYPE_CHUNK,
53			.type	= ION_HEAP_TYPE_CHUNK,
54			.name	= "chunk",
55			.size	= SZ_4M,
56			.align	= SZ_16K,
57			.priv	= (void *)(SZ_16K),
58		},
59};
60
61static struct ion_platform_data dummy_ion_pdata = {
62	.nr = ARRAY_SIZE(dummy_heaps),
63	.heaps = dummy_heaps,
64};
65
66static int __init ion_dummy_init(void)
67{
68	int i, err;
69
70	idev = ion_device_create(NULL);
71	heaps = kcalloc(dummy_ion_pdata.nr, sizeof(struct ion_heap *),
72			GFP_KERNEL);
73	if (!heaps)
74		return -ENOMEM;
75
76
77	/* Allocate a dummy carveout heap */
78	carveout_ptr = alloc_pages_exact(
79				dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size,
80				GFP_KERNEL);
81	if (carveout_ptr)
82		dummy_heaps[ION_HEAP_TYPE_CARVEOUT].base =
83						virt_to_phys(carveout_ptr);
84	else
85		pr_err("ion_dummy: Could not allocate carveout\n");
86
87	/* Allocate a dummy chunk heap */
88	chunk_ptr = alloc_pages_exact(
89				dummy_heaps[ION_HEAP_TYPE_CHUNK].size,
90				GFP_KERNEL);
91	if (chunk_ptr)
92		dummy_heaps[ION_HEAP_TYPE_CHUNK].base = virt_to_phys(chunk_ptr);
93	else
94		pr_err("ion_dummy: Could not allocate chunk\n");
95
96	for (i = 0; i < dummy_ion_pdata.nr; i++) {
97		struct ion_platform_heap *heap_data = &dummy_ion_pdata.heaps[i];
98
99		if (heap_data->type == ION_HEAP_TYPE_CARVEOUT &&
100							!heap_data->base)
101			continue;
102
103		if (heap_data->type == ION_HEAP_TYPE_CHUNK && !heap_data->base)
104			continue;
105
106		heaps[i] = ion_heap_create(heap_data);
107		if (IS_ERR_OR_NULL(heaps[i])) {
108			err = PTR_ERR(heaps[i]);
109			goto err;
110		}
111		ion_device_add_heap(idev, heaps[i]);
112	}
113	return 0;
114err:
115	for (i = 0; i < dummy_ion_pdata.nr; i++) {
116		if (heaps[i])
117			ion_heap_destroy(heaps[i]);
118	}
119	kfree(heaps);
120
121	if (carveout_ptr) {
122		free_pages_exact(carveout_ptr,
123				dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size);
124		carveout_ptr = NULL;
125	}
126	if (chunk_ptr) {
127		free_pages_exact(chunk_ptr,
128				dummy_heaps[ION_HEAP_TYPE_CHUNK].size);
129		chunk_ptr = NULL;
130	}
131	return err;
132}
133device_initcall(ion_dummy_init);
134
135static void __exit ion_dummy_exit(void)
136{
137	int i;
138
139	ion_device_destroy(idev);
140
141	for (i = 0; i < dummy_ion_pdata.nr; i++)
142		ion_heap_destroy(heaps[i]);
143	kfree(heaps);
144
145	if (carveout_ptr) {
146		free_pages_exact(carveout_ptr,
147				dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size);
148		carveout_ptr = NULL;
149	}
150	if (chunk_ptr) {
151		free_pages_exact(chunk_ptr,
152				dummy_heaps[ION_HEAP_TYPE_CHUNK].size);
153		chunk_ptr = NULL;
154	}
155
156	return;
157}
158__exitcall(ion_dummy_exit);
159