xref: /OK3568_Linux_fs/kernel/drivers/staging/android/ion/rockchip/rockchip_ion.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * drivers/staging/android/ion/rockchip/rockchip_ion.c
3  *
4  * Copyright (C) 2014 ROCKCHIP, 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/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
20 #include <linux/dma-buf.h>
21 #include <linux/dma-contiguous.h>
22 #include <linux/of.h>
23 #include <linux/of_reserved_mem.h>
24 #include <linux/rockchip_ion.h>
25 
26 #include "../ion_priv.h"
27 
28 struct ion_device *rockchip_ion_dev;
29 static struct ion_heap **heaps;
30 
31 struct ion_heap_desc {
32 	unsigned int id;
33 	enum ion_heap_type type;
34 	const char *name;
35 };
36 
37 static struct ion_heap_desc ion_heap_meta[] = {
38 	{
39 		.id	= ION_HEAP_TYPE_SYSTEM,
40 		.type	= ION_HEAP_TYPE_SYSTEM,
41 		.name	= "system-heap",
42 	}, {
43 		.id	= ION_HEAP_TYPE_CARVEOUT,
44 		.type	= ION_HEAP_TYPE_CARVEOUT,
45 		.name	= "carveout-heap",
46 	}, {
47 		.id	= ION_HEAP_TYPE_DMA,
48 		.type	= ION_HEAP_TYPE_DMA,
49 		.name	= "cma-heap",
50 	},
51 };
52 
53 /* Return result of step for heap array. */
rk_ion_of_heap(struct ion_platform_heap * myheap,struct device_node * node)54 static int rk_ion_of_heap(struct ion_platform_heap *myheap,
55 			  struct device_node *node)
56 {
57 	unsigned int reg[2] = {0,};
58 	int itype;
59 
60 	for (itype = 0; itype < ARRAY_SIZE(ion_heap_meta); itype++) {
61 		if (strcmp(ion_heap_meta[itype].name, node->name))
62 			continue;
63 
64 		myheap->name = node->name;
65 		myheap->align = SZ_1M;
66 		myheap->id = ion_heap_meta[itype].id;
67 		if (!strcmp("cma-heap", node->name)) {
68 			myheap->type = ION_HEAP_TYPE_DMA;
69 			if (!of_property_read_u32_array(node, "reg", reg, 2)) {
70 				myheap->base = reg[0];
71 				myheap->size = reg[1];
72 			}
73 			return 1;
74 		}
75 
76 		if (!strcmp("system-heap", node->name)) {
77 			myheap->type = ION_HEAP_TYPE_SYSTEM;
78 			return 1;
79 		}
80 	}
81 
82 	return 0;
83 }
84 
rk_ion_of(struct device_node * node)85 static struct ion_platform_data *rk_ion_of(struct device_node *node)
86 {
87 	struct ion_platform_data *pdata;
88 	int iheap = 0;
89 	struct device_node *child;
90 	struct ion_platform_heap *myheap;
91 
92 	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
93 	if (!pdata)
94 		return NULL;
95 
96 	pdata->nr = of_get_child_count(node);
97 again:
98 	pdata->heaps = kcalloc(pdata->nr, sizeof(*myheap), GFP_KERNEL);
99 	for_each_child_of_node(node, child) {
100 		iheap += rk_ion_of_heap(&pdata->heaps[iheap], child);
101 	}
102 
103 	if (pdata->nr != iheap) {
104 		pdata->nr = iheap;
105 		iheap = 0;
106 		kfree(pdata->heaps);
107 		pr_err("%s: mismatch, repeating\n", __func__);
108 		goto again;
109 	}
110 
111 	return pdata;
112 }
113 
rk_ion_probe(struct platform_device * pdev)114 static int rk_ion_probe(struct platform_device *pdev)
115 {
116 	int err;
117 	int i;
118 	struct ion_platform_data *pdata = pdev->dev.platform_data;
119 	struct ion_device *idev;
120 
121 	err = of_reserved_mem_device_init(&pdev->dev);
122 	if (err)
123 		pr_debug("No reserved memory region assign to ion\n");
124 
125 	if (!pdata) {
126 		pdata = rk_ion_of(pdev->dev.of_node);
127 		pdev->dev.platform_data = pdata;
128 	}
129 
130 	heaps = kcalloc(pdata->nr, sizeof(*heaps), GFP_KERNEL);
131 
132 	idev = ion_device_create(NULL);
133 	if (IS_ERR_OR_NULL(idev)) {
134 		kfree(heaps);
135 		return PTR_ERR(idev);
136 	}
137 
138 	ion_device_set_platform(idev, &pdev->dev);
139 	rockchip_ion_dev = idev;
140 
141 	/* create the heaps as specified in the board file */
142 	for (i = 0; i < pdata->nr; i++) {
143 		struct ion_platform_heap *heap_data = &pdata->heaps[i];
144 
145 		heap_data->priv = &pdev->dev;
146 		heaps[i] = ion_heap_create(heap_data);
147 		if (IS_ERR_OR_NULL(heaps[i])) {
148 			err = PTR_ERR(heaps[i]);
149 			goto err;
150 		}
151 		pr_info("rockchip ion: success to create - %s\n",
152 			heaps[i]->name);
153 		ion_device_add_heap(idev, heaps[i]);
154 	}
155 	platform_set_drvdata(pdev, idev);
156 
157 	return 0;
158 err:
159 	for (i = 0; i < pdata->nr; i++) {
160 		if (heaps[i])
161 			ion_heap_destroy(heaps[i]);
162 	}
163 
164 	kfree(heaps);
165 	return err;
166 }
167 
rk_ion_remove(struct platform_device * pdev)168 static int rk_ion_remove(struct platform_device *pdev)
169 {
170 	struct ion_platform_data *pdata = pdev->dev.platform_data;
171 	struct ion_device *idev = platform_get_drvdata(pdev);
172 	int i;
173 
174 	ion_device_destroy(idev);
175 	for (i = 0; i < pdata->nr; i++)
176 		ion_heap_destroy(heaps[i]);
177 
178 	kfree(heaps);
179 	return 0;
180 }
181 
rockchip_ion_client_create(const char * name)182 struct ion_client *rockchip_ion_client_create(const char *name)
183 {
184 	if (!rockchip_ion_dev) {
185 		pr_err("rockchip ion idev is NULL\n");
186 		return NULL;
187 	}
188 
189 	return ion_client_create(rockchip_ion_dev, name);
190 }
191 EXPORT_SYMBOL_GPL(rockchip_ion_client_create);
192 
193 static const struct of_device_id rk_ion_match[] = {
194 	{ .compatible = "rockchip,ion", },
195 	{}
196 };
197 
198 static struct platform_driver ion_driver = {
199 	.probe = rk_ion_probe,
200 	.remove = rk_ion_remove,
201 	.driver = {
202 		.name = "ion-rk",
203 		.owner = THIS_MODULE,
204 		.of_match_table = of_match_ptr(rk_ion_match),
205 	},
206 };
207 
rk_ion_init(void)208 static int __init rk_ion_init(void)
209 {
210 	return platform_driver_register(&ion_driver);
211 }
212 
rk_ion_exit(void)213 static void __exit rk_ion_exit(void)
214 {
215 	platform_driver_unregister(&ion_driver);
216 }
217 
218 subsys_initcall(rk_ion_init);
219 module_exit(rk_ion_exit);
220 
221 MODULE_AUTHOR("Meiyou.chen <cmy@rock-chips.com>");
222 MODULE_DESCRIPTION("ROCKCHIP Ion driver");
223 MODULE_LICENSE("GPL v2");
224 MODULE_DEVICE_TABLE(of, rk_ion_match);
225