diff options
author | Fei Wang <w.f@huawei.com> | 2014-12-10 14:52:09 +0800 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2016-03-21 12:10:19 -0700 |
commit | 6eac77caff9f2769789cf109da7ebea86f6513b1 (patch) | |
tree | dda88bf71c98209ee1aac26d1262401620613264 | |
parent | eca38125d69f503db49ec8fdb3c9658f6d1acbd8 (diff) | |
download | hikey-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.txt | 6 | ||||
-rw-r--r-- | drivers/staging/android/ion/Kconfig | 6 | ||||
-rw-r--r-- | drivers/staging/android/ion/Makefile | 2 | ||||
-rw-r--r-- | drivers/staging/android/ion/hisilicon/Makefile | 2 | ||||
-rw-r--r-- | drivers/staging/android/ion/hisilicon/hisi_ion.c | 248 | ||||
-rw-r--r-- | include/linux/hisi_ion.h | 56 |
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 |