#include <linux/mm.h>
#include "../ion_priv.h"
#include "../ion.h"
+#include "../ion_of.h"
-struct hi6220_ion_type_table {
- const char *name;
- enum ion_heap_type type;
+struct hisi_ion_dev {
+ struct ion_heap **heaps;
+ struct ion_device *idev;
+ struct ion_platform_data *data;
};
-static struct hi6220_ion_type_table ion_type_table[] = {
- {"ion_system", ION_HEAP_TYPE_SYSTEM},
- {"ion_system_contig", ION_HEAP_TYPE_SYSTEM_CONTIG},
- {"ion_carveout", ION_HEAP_TYPE_CARVEOUT},
- {"ion_chunk", ION_HEAP_TYPE_CHUNK},
- {"ion_dma", ION_HEAP_TYPE_DMA},
- {"ion_custom", ION_HEAP_TYPE_CUSTOM},
+static struct ion_of_heap hisi_heaps[] = {
+ PLATFORM_HEAP("hisilicon,sys_user", 0,
+ ION_HEAP_TYPE_SYSTEM, "sys_user"),
+ PLATFORM_HEAP("hisilicon,sys_contig", 1,
+ ION_HEAP_TYPE_SYSTEM_CONTIG, "sys_contig"),
+ PLATFORM_HEAP("hisilicon,cma", ION_HEAP_TYPE_DMA, ION_HEAP_TYPE_DMA,
+ "cma"),
+ {}
};
-static struct ion_device *idev;
-static int num_heaps;
-static struct ion_heap **heaps;
-static struct ion_platform_heap **heaps_data;
-
-static int get_type_by_name(const char *name, enum ion_heap_type *type)
+static int hi6220_ion_probe(struct platform_device *pdev)
{
+ struct hisi_ion_dev *ipdev;
int i;
- for (i = 0; i < ARRAY_SIZE(ion_type_table); i++) {
- if (strncmp(name, ion_type_table[i].name, strlen(name)))
- continue;
-
- *type = ion_type_table[i].type;
- return 0;
- }
-
- return -EINVAL;
-}
-
-static int hi6220_set_platform_data(struct platform_device *pdev)
-{
- unsigned int base;
- unsigned int size;
- unsigned int id;
- const char *heap_name;
- const char *type_name;
- enum ion_heap_type type;
- int ret;
- struct device_node *np;
- struct ion_platform_heap *p_data;
- const struct device_node *dt_node = pdev->dev.of_node;
- int index = 0;
-
- for_each_child_of_node(dt_node, np)
- num_heaps++;
-
- heaps_data = devm_kzalloc(&pdev->dev,
- sizeof(struct ion_platform_heap *) *
- num_heaps,
- GFP_KERNEL);
- if (!heaps_data)
+ ipdev = devm_kzalloc(&pdev->dev, sizeof(*ipdev), GFP_KERNEL);
+ if (!ipdev)
return -ENOMEM;
- for_each_child_of_node(dt_node, np) {
- ret = of_property_read_string(np, "heap-name", &heap_name);
- if (ret < 0) {
- pr_err("check the name of node %s\n", np->name);
- continue;
- }
-
- ret = of_property_read_u32(np, "heap-id", &id);
- if (ret < 0) {
- pr_err("check the id %s\n", np->name);
- continue;
- }
-
- ret = of_property_read_u32(np, "heap-base", &base);
- if (ret < 0) {
- pr_err("check the base of node %s\n", np->name);
- continue;
- }
-
- ret = of_property_read_u32(np, "heap-size", &size);
- if (ret < 0) {
- pr_err("check the size of node %s\n", np->name);
- continue;
- }
-
- ret = of_property_read_string(np, "heap-type", &type_name);
- if (ret < 0) {
- pr_err("check the type of node %s\n", np->name);
- continue;
- }
-
- ret = get_type_by_name(type_name, &type);
- if (ret < 0) {
- pr_err("type name error %s!\n", type_name);
- continue;
- }
- pr_info("heap index %d : name %s base 0x%x size 0x%x id %d type %d\n",
- index, heap_name, base, size, id, type);
-
- p_data = devm_kzalloc(&pdev->dev,
- sizeof(struct ion_platform_heap),
- GFP_KERNEL);
- if (!p_data)
- return -ENOMEM;
+ platform_set_drvdata(pdev, ipdev);
- p_data->name = heap_name;
- p_data->base = base;
- p_data->size = size;
- p_data->id = id;
- p_data->type = type;
+ ipdev->idev = ion_device_create(NULL);
+ if (!ipdev->idev)
+ return -ENOMEM;
- heaps_data[index] = p_data;
- index++;
- }
- return 0;
-}
+ ipdev->data = ion_parse_dt(pdev, hisi_heaps);
+ if (IS_ERR(ipdev->data))
+ return PTR_ERR(ipdev->data);
-static int hi6220_ion_probe(struct platform_device *pdev)
-{
- int i;
- int err;
- static struct ion_platform_heap *p_heap;
-
- idev = ion_device_create(NULL);
- err = hi6220_set_platform_data(pdev);
- if (err) {
- pr_err("ion set platform data error!\n");
- goto err_free_idev;
- }
- heaps = devm_kzalloc(&pdev->dev,
- sizeof(struct ion_heap *) * num_heaps,
- GFP_KERNEL);
- if (!heaps) {
- err = -ENOMEM;
- goto err_free_idev;
+ ipdev->heaps = devm_kzalloc(&pdev->dev,
+ sizeof(struct ion_heap)*ipdev->data->nr,
+ GFP_KERNEL);
+ if (!ipdev->heaps) {
+ ion_destroy_platform_data(ipdev->data);
+ return -ENOMEM;
}
- /*
- * create the heaps as specified in the dts file
- */
- for (i = 0; i < num_heaps; i++) {
- p_heap = heaps_data[i];
- heaps[i] = ion_heap_create(p_heap);
- if (IS_ERR_OR_NULL(heaps[i])) {
- err = PTR_ERR(heaps[i]);
- goto err_free_heaps;
+ for (i = 0; i < ipdev->data->nr; i++) {
+ ipdev->heaps[i] = ion_heap_create(&ipdev->data->heaps[i]);
+ if (!ipdev->heaps) {
+ ion_destroy_platform_data(ipdev->data);
+ return -ENOMEM;
}
-
- ion_device_add_heap(idev, heaps[i]);
-
- pr_info("%s: adding heap %s of type %d with %lx@%lx\n",
- __func__, p_heap->name, p_heap->type,
- p_heap->base, (unsigned long)p_heap->size);
+ ion_device_add_heap(ipdev->idev, ipdev->heaps[i]);
}
- return err;
-
-err_free_heaps:
- for (i = 0; i < num_heaps; ++i) {
- ion_heap_destroy(heaps[i]);
- heaps[i] = NULL;
- }
-err_free_idev:
- ion_device_destroy(idev);
-
- return err;
+ return 0;
}
static int hi6220_ion_remove(struct platform_device *pdev)
{
+ struct hisi_ion_dev *ipdev;
int i;
- for (i = 0; i < num_heaps; i++) {
- ion_heap_destroy(heaps[i]);
- heaps[i] = NULL;
+ ipdev = platform_get_drvdata(pdev);
+
+ for (i = 0; i < ipdev->data->nr; i++) {
+ ion_heap_destroy(ipdev->heaps[i]);
}
- ion_device_destroy(idev);
+ ion_destroy_platform_data(ipdev->data);
+ ion_device_destroy(ipdev->idev);
return 0;
}