aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFei Wang <w.f@huawei.com>2014-12-10 14:52:09 +0800
committerJohn Stultz <john.stultz@linaro.org>2016-03-21 12:10:19 -0700
commit6eac77caff9f2769789cf109da7ebea86f6513b1 (patch)
treedda88bf71c98209ee1aac26d1262401620613264
parenteca38125d69f503db49ec8fdb3c9658f6d1acbd8 (diff)
downloadhikey-clang-6eac77caff9f2769789cf109da7ebea86f6513b1.tar.gz
ion: Add hisi ion core driver for hi6220 SoC.
This patch add hisilicon ion core driver for hi6220 SoC. Now it use preserve memory, not use iommu. Signed-off-by: Fei Wang <w.f@huawei.com> [jstultz: Cherry-picked, and folded in warning fixes from Fei Wang, as well as included some of my own build fixups] Signed-off-by: John Stultz <john.stultz@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt6
-rw-r--r--drivers/staging/android/ion/Kconfig6
-rw-r--r--drivers/staging/android/ion/Makefile2
-rw-r--r--drivers/staging/android/ion/hisilicon/Makefile2
-rw-r--r--drivers/staging/android/ion/hisilicon/hisi_ion.c248
-rw-r--r--include/linux/hisi_ion.h56
6 files changed, 319 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 6ac7c000af22..58495ea35c4b 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -229,3 +229,9 @@ Required Properties:
[1]: bootwrapper size
[2]: relocation physical address
[3]: relocation size
+
+-----------------------------------------------------------------------
+Hisilicon ion
+
+Required properties:
+- compatible : "hisilicon,ion";
diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig
index 356e10969272..970cce136a58 100644
--- a/drivers/staging/android/ion/Kconfig
+++ b/drivers/staging/android/ion/Kconfig
@@ -27,6 +27,12 @@ config ION_DUMMY
one doesn't have access to hardware drivers that
use ION.
+config ION_HISI
+ tristate "Ion for Hisi"
+ depends on ARCH_HISI && ION
+ help
+ Choose this option if you wish to use ion on an Hisilicon platform
+
config ION_TEGRA
tristate "Ion for Tegra"
depends on ARCH_TEGRA && ION
diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile
index b56fd2bf2b4f..4d57f46133bf 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -7,4 +7,4 @@ endif
obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o
obj-$(CONFIG_ION_TEGRA) += tegra/
-
+obj-$(CONFIG_ION_HISI) += hisilicon/
diff --git a/drivers/staging/android/ion/hisilicon/Makefile b/drivers/staging/android/ion/hisilicon/Makefile
new file mode 100644
index 000000000000..f123a57ce456
--- /dev/null
+++ b/drivers/staging/android/ion/hisilicon/Makefile
@@ -0,0 +1,2 @@
+ccflags-y += -I$(srctree)/drivers/staging/android
+obj-y += hisi_ion.o
diff --git a/drivers/staging/android/ion/hisilicon/hisi_ion.c b/drivers/staging/android/ion/hisilicon/hisi_ion.c
new file mode 100644
index 000000000000..20f68e573cf3
--- /dev/null
+++ b/drivers/staging/android/ion/hisilicon/hisi_ion.c
@@ -0,0 +1,248 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#define pr_fmt(fmt) "ion: " fmt
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/hisi_ion.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include "../ion_priv.h"
+
+struct hisi_ion_name_id_table {
+ const char *name;
+ unsigned int id;
+};
+
+static struct hisi_ion_name_id_table name_id_table[] __initdata = {
+ {"fb", ION_FB_HEAP_ID},
+ {"vpu", ION_VPU_HEAP_ID},
+ {"jpu", ION_JPU_HEAP_ID},
+ {"gralloc-carveout", ION_GRALLOC_HEAP_ID},
+ {"overlay", ION_OVERLAY_HEAP_ID},
+ {"sys_user", ION_SYSTEM_HEAP_ID},
+ {"sys_contig", ION_SYSTEM_CONTIG_HEAP_ID},
+};
+
+struct hisi_ion_type_id_table {
+ const char *name;
+ enum ion_heap_type type;
+};
+
+static struct hisi_ion_type_id_table type_id_table[] = {
+ {"ion_system_contig", ION_HEAP_TYPE_SYSTEM_CONTIG},
+ {"ion_system", ION_HEAP_TYPE_SYSTEM},
+ {"ion_carveout", ION_HEAP_TYPE_CARVEOUT},
+ {"ion_chunk", ION_HEAP_TYPE_CHUNK},
+ {"ion_dma", ION_HEAP_TYPE_DMA},
+ {"ion_custom", ION_HEAP_TYPE_CUSTOM},
+};
+
+#define HISI_ION_HEAP_NUM 16
+
+static struct ion_platform_data hisi_ion_platform_data = {0};
+static struct ion_platform_heap hisi_ion_platform_heap[HISI_ION_HEAP_NUM] = {{0} };
+
+static struct ion_device *hisi_ion_device;
+static struct ion_heap *hisi_ion_heap[HISI_ION_HEAP_NUM] = {NULL};
+
+int hisi_ion_get_heap_info(unsigned int id, struct ion_heap_info_data *data)
+{
+ int i;
+
+ BUG_ON(!data);
+
+ for (i = 0; i < hisi_ion_platform_data.nr; i++) {
+ if (hisi_ion_platform_heap[i].id == id) {
+ data->heap_phy = hisi_ion_platform_heap[i].base;
+ data->heap_size = hisi_ion_platform_heap[i].size;
+ strncpy((void *)data->name, (void *)hisi_ion_platform_heap[i].name, HISI_ION_NAME_LEN);
+ pr_info("heap info : id %d name %s phy 0x%llx size %u\n",
+ id, data->name, data->heap_phy, data->heap_size);
+ return 0;
+ }
+ }
+ pr_err("in %s please check the id %d\n", __func__, id);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(hisi_ion_get_heap_info);
+
+struct ion_device *get_ion_device(void)
+{
+ return hisi_ion_device;
+}
+EXPORT_SYMBOL(get_ion_device);
+
+static int __init get_id_by_name(const char *name, unsigned int *id)
+{
+ int i, n;
+
+ n = sizeof(name_id_table)/sizeof(name_id_table[0]);
+ for (i = 0; i < n; i++) {
+ if (strncmp(name, name_id_table[i].name, HISI_ION_NAME_LEN))
+ continue;
+
+ *id = name_id_table[i].id;
+ return 0;
+ }
+ return -1;
+}
+
+static int __init get_type_by_name(const char *name, enum ion_heap_type *type)
+{
+ int i, n;
+
+ n = sizeof(type_id_table)/sizeof(type_id_table[0]);
+ for (i = 0; i < n; i++) {
+ if (strncmp(name, type_id_table[i].name, HISI_ION_NAME_LEN))
+ continue;
+
+ *type = type_id_table[i].type;
+ return 0;
+ }
+
+ return -1;
+}
+
+static int __init hisi_ion_setup_platform_data(struct platform_device *dev)
+{
+ struct device_node *node, *np;
+ const char *heap_name;
+ const char *type_name;
+ unsigned int id;
+ unsigned int range[2] = {0, 0};
+ enum ion_heap_type type;
+ int ret;
+ int index = 0;
+
+ node = dev->dev.of_node;
+ for_each_child_of_node(node, np) {
+ ret = of_property_read_string(np, "heap-name", &heap_name);
+ if (ret < 0) {
+ pr_err("in node %s please check the name property of node %s\n", __func__, np->name);
+ continue;
+ }
+
+ ret = get_id_by_name(heap_name, &id);
+ if (ret < 0) {
+ pr_err("in node %s please check the name %s\n", __func__, heap_name);
+ continue;
+ }
+
+ ret = of_property_read_u32_array(np, "heap-range", range, ARRAY_SIZE(range));
+ if (ret < 0) {
+ pr_err("in node %s please check the range property of node %s\n", __func__, np->name);
+ continue;
+ }
+
+
+ ret = of_property_read_string(np, "heap-type", &type_name);
+ if (ret < 0) {
+ pr_err("in node %s please check the type property of node %s\n", __func__, np->name);
+ continue;
+ }
+
+ ret = get_type_by_name(type_name, &type);
+ if (ret < 0) {
+ pr_err("in node %s please check the type %s\n", __func__, type_name);
+ continue;
+ }
+
+ hisi_ion_platform_heap[index].name = heap_name;
+ hisi_ion_platform_heap[index].base = range[0];
+ hisi_ion_platform_heap[index].size = range[1];
+ hisi_ion_platform_heap[index].id = id;
+ hisi_ion_platform_heap[index].type = type;
+
+ index++;
+ }
+
+ hisi_ion_platform_data.nr = index;
+ hisi_ion_platform_data.heaps = hisi_ion_platform_heap;
+
+ return 0;
+}
+
+static int __init hisi_ion_probe(struct platform_device *pdev)
+{
+ int i, err;
+ struct ion_heap *heap;
+ struct ion_platform_heap *heap_data;
+
+ if (hisi_ion_setup_platform_data(pdev)) {
+ pr_err("hisi_ion_setup_platform_data is failed\n");
+ return -EINVAL;
+ }
+
+ hisi_ion_device = ion_device_create(NULL);
+ if (IS_ERR_OR_NULL(hisi_ion_device))
+ return PTR_ERR(hisi_ion_device);
+ /*
+ * create the heaps as specified in the board file
+ */
+ for (i = 0; i < hisi_ion_platform_data.nr; i++) {
+ heap_data = &hisi_ion_platform_data.heaps[i];
+ heap = ion_heap_create(heap_data);
+ if (IS_ERR_OR_NULL(heap)) {
+ err = PTR_ERR(heap);
+ goto out;
+ }
+
+ ion_device_add_heap(hisi_ion_device, heap);
+ hisi_ion_heap[i] = heap;
+ }
+ platform_set_drvdata(pdev, hisi_ion_device);
+
+ return 0;
+out:
+ for (i = 0; i < HISI_ION_HEAP_NUM; i++) {
+ if (!hisi_ion_heap[i])
+ continue;
+ ion_heap_destroy(hisi_ion_heap[i]);
+ hisi_ion_heap[i] = NULL;
+ }
+ return err;
+}
+
+static int hisi_ion_remove(struct platform_device *pdev)
+{
+ int i;
+
+ ion_device_destroy(hisi_ion_device);
+ for (i = 0; i < HISI_ION_HEAP_NUM; i++) {
+ if (!hisi_ion_heap[i])
+ continue;
+ ion_heap_destroy(hisi_ion_heap[i]);
+ hisi_ion_heap[i] = NULL;
+ }
+
+ return 0;
+}
+
+static struct of_device_id hisi_ion_match_table[] = {
+ {.compatible = "hisilicon,ion"},
+ {},
+};
+
+static struct platform_driver hisi_ion_driver = {
+ .probe = hisi_ion_probe,
+ .remove = hisi_ion_remove,
+ .driver = {
+ .name = "ion",
+ .of_match_table = hisi_ion_match_table,
+ },
+};
+
+module_platform_driver(hisi_ion_driver);
diff --git a/include/linux/hisi_ion.h b/include/linux/hisi_ion.h
new file mode 100644
index 000000000000..b1e003378b24
--- /dev/null
+++ b/include/linux/hisi_ion.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_HISI_ION_H
+#define _LINUX_HISI_ION_H
+
+#include <ion/ion.h>
+
+/**
+ * These are the only ids that should be used for Ion heap ids.
+ * The ids listed are the order in which allocation will be attempted
+ * if specified. Don't swap the order of heap ids unless you know what
+ * you are doing!
+ * Id's are spaced by purpose to allow new Id's to be inserted in-between (for
+ * possible fallbacks)
+ */
+
+enum ion_heap_ids {
+ ION_SYSTEM_HEAP_ID = 0,
+ ION_SYSTEM_CONTIG_HEAP_ID = 1,
+ ION_GRALLOC_HEAP_ID = 2,
+ ION_OVERLAY_HEAP_ID = 7,
+ ION_FB_HEAP_ID = 10,
+ ION_VPU_HEAP_ID = 11,
+ ION_JPU_HEAP_ID = 12,
+};
+
+
+/**
+ * Macro should be used with ion_heap_ids defined above.
+ */
+#define ION_HEAP(bit) (1 << (bit))
+#define HISI_ION_NAME_LEN 16
+
+struct ion_heap_info_data{
+ char name[HISI_ION_NAME_LEN];
+ phys_addr_t heap_phy;
+ unsigned int heap_size;
+};
+
+int hisi_ion_get_heap_info(unsigned int id,struct ion_heap_info_data* data);
+struct ion_device * get_ion_device(void);
+
+#endif