summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSong Bing <bing.song@nxp.com>2016-11-30 15:41:16 +0800
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:41:33 +0300
commitfb72a661a126d5d120b9256cddb5bc1d7ccd9f4b (patch)
treefbba1b17929938218511e71947092ea48f4ca790
parent264c7cd1d74915b5fab47a0f581afc7c81172e3c (diff)
MLK-13561 ion: Enable mxc ion driver
Enable mxc ion driver. ion driver can allocate physical continuous memory and can convert to physical address from DMA FD and virtual address if the memory is physical continuous. Signed-off-by: Song Bing bing.song@nxp.com
-rw-r--r--arch/arm/configs/imx_v7_defconfig2
-rw-r--r--drivers/staging/Makefile2
-rw-r--r--drivers/staging/android/Kconfig4
-rw-r--r--drivers/staging/android/ion/Kconfig8
-rw-r--r--drivers/staging/android/ion/Makefile2
-rw-r--r--drivers/staging/android/ion/ion.c38
-rw-r--r--drivers/staging/android/ion/ion_priv.h6
-rw-r--r--drivers/staging/android/ion/mxc/Makefile2
-rw-r--r--drivers/staging/android/ion/mxc/mxc_ion.c308
-rw-r--r--drivers/staging/android/uapi/ion.h25
10 files changed, 393 insertions, 4 deletions
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index 71f2ef3165ac..09a924753d35 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -385,6 +385,8 @@ CONFIG_IMX7D_ADC=y
CONFIG_VF610_ADC=y
CONFIG_PWM=y
CONFIG_PWM_IMX=y
+CONFIG_ION=y
+CONFIG_ION_MXC=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 2fa9745db614..27a8ba7ee973 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -22,7 +22,7 @@ obj-$(CONFIG_FB_XGI) += xgifb/
obj-$(CONFIG_USB_EMXX) += emxx_udc/
obj-$(CONFIG_SPEAKUP) += speakup/
obj-$(CONFIG_MFD_NVEC) += nvec/
-obj-$(CONFIG_ANDROID) += android/
+obj-y += android/
obj-$(CONFIG_STAGING_BOARD) += board/
obj-$(CONFIG_LTE_GDM724X) += gdm724x/
obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 6c00d6f765c6..6b2b942ebfc3 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -24,8 +24,8 @@ config ANDROID_LOW_MEMORY_KILLER
scripts (/init.rc), and it defines priority values with minimum free memory size
for each priority.
-source "drivers/staging/android/ion/Kconfig"
-
endif # if ANDROID
+source "drivers/staging/android/ion/Kconfig"
+
endmenu
diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig
index c8fb4134c55d..22ab23074c16 100644
--- a/drivers/staging/android/ion/Kconfig
+++ b/drivers/staging/android/ion/Kconfig
@@ -42,6 +42,13 @@ config ION_HISI
source "drivers/staging/android/ion/hisilicon/Kconfig"
+config ION_MXC
+ tristate "Ion for imx platform"
+ depends on ION
+ select VIDEOBUF2_DMA_CONTIG
+ help
+ Choose this option if you wish to use ion on imx platform.
+
config ION_OF
bool "Devicetree support for Ion"
depends on ION && OF_ADDRESS
@@ -52,3 +59,4 @@ config ION_OF
extensions
If using Ion and devicetree, you should say Y here
+
diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile
index 5d630a088381..724f014cb005 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -9,5 +9,5 @@ endif
obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o
obj-$(CONFIG_ION_TEGRA) += tegra/
obj-$(CONFIG_ION_HISI) += hisilicon/
+obj-$(CONFIG_ION_MXC) += mxc/
obj-$(CONFIG_ION_OF) += ion_of.o
-
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 6f9974cb0e15..d280d14a95e0 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -3,6 +3,7 @@
* drivers/staging/android/ion/ion.c
*
* Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -364,6 +365,26 @@ struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
return handle;
}
+/* for used in mxc_ion.c */
+int ion_handle_put_wrap(struct ion_handle *handle)
+{
+ return ion_handle_put(handle);
+}
+
+struct ion_handle *ion_handle_get_by_id_wrap(struct ion_client *client,
+ int id)
+{
+ return ion_handle_get_by_id(client, id);
+}
+
+struct device *ion_device_get_by_client(struct ion_client *client)
+{
+ if (client)
+ return client->dev->dev.this_device;
+ else
+ return NULL;
+}
+
static bool ion_handle_validate(struct ion_client *client,
struct ion_handle *handle)
{
@@ -1016,6 +1037,21 @@ static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
return 0;
}
+static void *ion_dma_buf_vmap(struct dma_buf *dmabuf)
+{
+ struct ion_buffer *buffer = dmabuf->priv;
+
+ if (ion_dma_buf_begin_cpu_access(dmabuf, DMA_NONE) != 0)
+ return NULL;
+
+ return buffer->vaddr;
+}
+
+static void ion_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
+{
+ ion_dma_buf_end_cpu_access(dmabuf, DMA_NONE);
+}
+
static struct dma_buf_ops dma_buf_ops = {
.map_dma_buf = ion_map_dma_buf,
.unmap_dma_buf = ion_unmap_dma_buf,
@@ -1027,6 +1063,8 @@ static struct dma_buf_ops dma_buf_ops = {
.kunmap_atomic = ion_dma_buf_kunmap,
.kmap = ion_dma_buf_kmap,
.kunmap = ion_dma_buf_kunmap,
+ .vmap = ion_dma_buf_vmap,
+ .vunmap = ion_dma_buf_vunmap,
};
struct dma_buf *ion_share_dma_buf(struct ion_client *client,
diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h
index 3c3b3245275d..2d4ef0d93d99 100644
--- a/drivers/staging/android/ion/ion_priv.h
+++ b/drivers/staging/android/ion/ion_priv.h
@@ -2,6 +2,7 @@
* drivers/staging/android/ion/ion_priv.h
*
* Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -470,4 +471,9 @@ int ion_handle_put(struct ion_handle *handle);
int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query);
+int ion_handle_put_wrap(struct ion_handle *handle);
+struct ion_handle *ion_handle_get_by_id_wrap(struct ion_client *client,
+ int id);
+struct device *ion_device_get_by_client(struct ion_client *client);
+
#endif /* _ION_PRIV_H */
diff --git a/drivers/staging/android/ion/mxc/Makefile b/drivers/staging/android/ion/mxc/Makefile
new file mode 100644
index 000000000000..df308e51837a
--- /dev/null
+++ b/drivers/staging/android/ion/mxc/Makefile
@@ -0,0 +1,2 @@
+ccflags-y += -I../
+obj-y += mxc_ion.o
diff --git a/drivers/staging/android/ion/mxc/mxc_ion.c b/drivers/staging/android/ion/mxc/mxc_ion.c
new file mode 100644
index 000000000000..14ae747a5385
--- /dev/null
+++ b/drivers/staging/android/ion/mxc/mxc_ion.c
@@ -0,0 +1,308 @@
+/*
+ * drivers/gpu/mxc/mxc_ion.c
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2012-2016 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/uaccess.h>
+#include <media/videobuf2-dma-contig.h>
+#include <linux/dma-buf.h>
+
+#include "../ion_priv.h"
+
+static struct ion_device *idev;
+static int num_heaps = 1;
+static struct ion_heap **heaps;
+static int cacheable;
+
+struct ion_platform_data *
+mxc_ion_parse_of(struct platform_device *pdev)
+{
+ struct ion_platform_data *pdata = 0;
+ const struct device_node *node = pdev->dev.of_node;
+ int ret = 0;
+ unsigned int val = 0;
+ struct ion_platform_heap *heap = NULL;
+
+ pdata = kzalloc(sizeof(struct ion_platform_data), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ heap = kzalloc(sizeof(struct ion_platform_heap), GFP_KERNEL);
+ if (!heap) {
+ kfree(pdata);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ heap->type = ION_HEAP_TYPE_DMA;
+ heap->priv = &pdev->dev;
+ heap->name = "mxc_ion";
+
+ pdata->heaps = heap;
+ pdata->nr = num_heaps;
+
+ ret = of_property_read_u32(node, "fsl,heap-cacheable", &val);
+ if (!ret)
+ cacheable = 1;
+
+ val = 0;
+ ret = of_property_read_u32(node, "fsl,heap-id", &val);
+ if (!ret)
+ heap->id = val;
+ else
+ heap->id = 0;
+
+ return pdata;
+}
+
+static long
+mxc_custom_ioctl(struct ion_client *client, unsigned int cmd, unsigned long arg)
+{
+ switch (cmd) {
+ case ION_IOC_PHYS:
+ {
+ struct ion_handle *handle;
+ struct ion_phys_data data;
+ struct device *dev;
+ void *vaddr;
+
+ if (copy_from_user(&data, (void __user *) arg,
+ sizeof(struct ion_phys_data)))
+ return -EFAULT;
+ handle = ion_handle_get_by_id_wrap(client, data.handle);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ vaddr = ion_map_kernel(client, handle);
+ ion_handle_put_wrap(handle);
+
+ if (IS_ERR(vaddr))
+ return PTR_ERR(vaddr);
+
+ dev = ion_device_get_by_client(client);
+ data.phys = virt_to_dma(dev, vaddr);
+
+ if (copy_to_user((void __user *) arg, &data,
+ sizeof(struct ion_phys_data)))
+ return -EFAULT;
+ return 0;
+ }
+ case ION_IOC_PHYS_DMA:
+ {
+ int ret = 0;
+ struct device *dev = NULL;
+ struct dma_buf *dmabuf = NULL;
+ unsigned long phys = 0;
+ u64 dma_mask = DMA_BIT_MASK(32);
+ size_t len = 0;
+ struct ion_phys_dma_data data;
+ const struct vb2_mem_ops *mem_ops =
+ &vb2_dma_contig_memops;
+ dma_addr_t *addr;
+ void *mem_priv;
+
+ if (copy_from_user(&data, (void __user *) arg,
+ sizeof(struct ion_phys_dma_data)))
+ return -EFAULT;
+
+ /* Get physical address from dmafd */
+ dmabuf = dma_buf_get(data.dmafd);
+ if (!dmabuf)
+ return -1;
+
+ dev = ion_device_get_by_client(client);
+ dev->dma_mask = &dma_mask;
+
+ mem_priv = mem_ops->attach_dmabuf(dev,
+ dmabuf, dmabuf->size,
+ DMA_BIDIRECTIONAL);
+ if (IS_ERR(mem_priv))
+ goto err1;
+ ret = mem_ops->map_dmabuf(mem_priv);
+ if (ret)
+ goto err0;
+
+ addr = mem_ops->cookie(mem_priv);
+ phys = *addr;
+ len = dmabuf->size;
+
+ data.phys = phys;
+ data.size = len;
+ if (copy_to_user((void __user *) arg, &data,
+ sizeof(struct ion_phys_dma_data))) {
+ ret = -EFAULT;
+ }
+
+ /* unmap and detach */
+ mem_ops->unmap_dmabuf(mem_priv);
+err0:
+ mem_ops->detach_dmabuf(mem_priv);
+err1:
+ dma_buf_put(dmabuf);
+
+ if (ret < 0)
+ return ret;
+ return 0;
+ }
+ case ION_IOC_PHYS_VIRT:
+ {
+ struct device *dev = NULL;
+ u64 dma_mask = DMA_BIT_MASK(32);
+ struct ion_phys_virt_data data;
+ const struct vb2_mem_ops *mem_ops =
+ &vb2_dma_contig_memops;
+ dma_addr_t *addr;
+ void *mem_priv;
+
+ if (copy_from_user(&data, (void __user *) arg,
+ sizeof(struct ion_phys_virt_data)))
+ return -EFAULT;
+
+ /* Get physical address from virtual address */
+ if (!data.virt)
+ return -1;
+
+ dev = ion_device_get_by_client(client);
+ dev->dma_mask = &dma_mask;
+
+ mem_priv = mem_ops->get_userptr(dev,
+ data.virt, data.size,
+ DMA_BIDIRECTIONAL);
+ if (IS_ERR(mem_priv))
+ return -1;
+
+ addr = mem_ops->cookie(mem_priv);
+ mem_ops->put_userptr(mem_priv);
+
+ data.phys = *addr;
+ if (copy_to_user((void __user *) arg, &data,
+ sizeof(struct ion_phys_virt_data)))
+ return -EFAULT;
+ return 0;
+ }
+ default:
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+int
+mxc_ion_probe(struct platform_device *pdev)
+{
+ struct ion_platform_data *pdata = NULL;
+ int pdata_is_created = 0;
+ int err;
+ int i;
+
+ if (pdev->dev.of_node) {
+ pdata = mxc_ion_parse_of(pdev);
+ pdata_is_created = 1;
+ } else {
+ pdata = pdev->dev.platform_data;
+ }
+
+ if (IS_ERR_OR_NULL(pdata))
+ return PTR_ERR(pdata);
+
+ num_heaps = pdata->nr;
+
+ heaps = kzalloc(sizeof(struct ion_heap *) * pdata->nr, GFP_KERNEL);
+
+ idev = ion_device_create(mxc_custom_ioctl);
+ if (IS_ERR_OR_NULL(idev)) {
+ err = PTR_ERR(idev);
+ goto err;
+ }
+
+ /* create the heaps as specified in the board file */
+ for (i = 0; i < num_heaps; i++) {
+ struct ion_platform_heap *heap_data = &pdata->heaps[i];
+
+ heaps[i] = ion_heap_create(heap_data);
+ if (IS_ERR_OR_NULL(heaps[i])) {
+ err = PTR_ERR(heaps[i]);
+ heaps[i] = NULL;
+ goto err;
+ }
+ ion_device_add_heap(idev, heaps[i]);
+ }
+ platform_set_drvdata(pdev, idev);
+ return 0;
+err:
+ for (i = 0; i < num_heaps; i++) {
+ if (heaps[i])
+ ion_heap_destroy(heaps[i]);
+ }
+ kfree(heaps);
+ if (pdata_is_created) {
+ kfree(pdata->heaps);
+ kfree(pdata);
+ }
+ return err;
+}
+
+int
+mxc_ion_remove(struct platform_device *pdev)
+{
+ struct ion_device *idev = platform_get_drvdata(pdev);
+ int i;
+
+ ion_device_destroy(idev);
+ for (i = 0; i < num_heaps; i++)
+ ion_heap_destroy(heaps[i]);
+ kfree(heaps);
+ return 0;
+}
+
+static struct of_device_id ion_match_table[] = {
+ {.compatible = "fsl,mxc-ion"},
+ {},
+};
+
+static struct platform_driver ion_driver = {
+ .probe = mxc_ion_probe,
+ .remove = mxc_ion_remove,
+ .driver = {
+ .name = "ion-mxc",
+ .of_match_table = ion_match_table,
+ },
+};
+
+static int __init
+ion_init(void)
+{
+ return platform_driver_register(&ion_driver);
+}
+
+static void __exit
+ion_exit(void)
+{
+ platform_driver_unregister(&ion_driver);
+}
+
+module_init(ion_init);
+module_exit(ion_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC ion allocator driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("fb");
diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h
index 14cd8738ecfc..401d59edcd0f 100644
--- a/drivers/staging/android/uapi/ion.h
+++ b/drivers/staging/android/uapi/ion.h
@@ -2,6 +2,7 @@
* drivers/staging/android/uapi/ion.h
*
* Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -46,6 +47,7 @@ enum ion_heap_type {
*/
};
+#define ION_CMA_HEAP_ID 0
#define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8)
/**
@@ -158,6 +160,23 @@ struct ion_heap_query {
__u32 reserved2;
};
+struct ion_phys_data {
+ ion_user_handle_t handle;
+ unsigned long phys;
+};
+
+struct ion_phys_dma_data {
+ unsigned long phys;
+ size_t size;
+ int dmafd;
+};
+
+struct ion_phys_virt_data {
+ unsigned long virt;
+ unsigned long phys;
+ size_t size;
+};
+
#define ION_IOC_MAGIC 'I'
/**
@@ -233,4 +252,10 @@ struct ion_heap_query {
#define ION_IOC_HEAP_QUERY _IOWR(ION_IOC_MAGIC, 8, \
struct ion_heap_query)
+#define ION_IOC_PHYS _IOWR(ION_IOC_MAGIC, 8, struct ion_phys_data)
+
+#define ION_IOC_PHYS_DMA _IOWR(ION_IOC_MAGIC, 9, struct ion_phys_dma_data)
+
+#define ION_IOC_PHYS_VIRT _IOWR(ION_IOC_MAGIC, 10, struct ion_phys_virt_data)
+
#endif /* _UAPI_LINUX_ION_H */