From patchwork Tue May 24 13:31:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 9133605 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 910E9607D5 for ; Tue, 24 May 2016 13:32:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 84B1F2821B for ; Tue, 24 May 2016 13:32:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7953F2828B; Tue, 24 May 2016 13:32:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CEABA2821B for ; Tue, 24 May 2016 13:32:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932543AbcEXNb6 (ORCPT ); Tue, 24 May 2016 09:31:58 -0400 Received: from mailout1.w1.samsung.com ([210.118.77.11]:20886 "EHLO mailout1.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932529AbcEXNb4 (ORCPT ); Tue, 24 May 2016 09:31:56 -0400 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout1.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0O7O00253O91VXA0@mailout1.w1.samsung.com>; Tue, 24 May 2016 14:31:49 +0100 (BST) X-AuditID: cbfec7f4-f796c6d000001486-9c-574457c5dda2 Received: from eusync4.samsung.com ( [203.254.199.214]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id 87.65.05254.5C754475; Tue, 24 May 2016 14:31:49 +0100 (BST) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync4.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0O7O00AJNO8VE550@eusync4.samsung.com>; Tue, 24 May 2016 14:31:49 +0100 (BST) From: Marek Szyprowski To: linux-media@vger.kernel.org, linux-samsung-soc@vger.kernel.org Cc: Marek Szyprowski , devicetree@vger.kernel.org, Sylwester Nawrocki , Kamil Debski , Kukjin Kim , Krzysztof Kozlowski , Javier Martinez Canillas , Uli Middelberg , Bartlomiej Zolnierkiewicz Subject: [PATCH v4 4/7] media: s5p-mfc: add iommu support Date: Tue, 24 May 2016 15:31:27 +0200 Message-id: <1464096690-23605-5-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <1464096690-23605-1-git-send-email-m.szyprowski@samsung.com> References: <1464096690-23605-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrGLMWRmVeSWpSXmKPExsVy+t/xa7pHw13CDd6+Y7LYOGM9q8X8I+dY Ld68XcNk8eP1BTaL1y8MLfofv2a26NmwldVixvl9TBZrj9xltzj8pp3V4tEWMQduj02rOtk8 NlzcyOqxpf8uu0ffllWMHp83yQWwRnHZpKTmZJalFunbJXBlNL48yVZwUa1i6Y8/LA2MbQpd jJwcEgImEkdWPWKEsMUkLtxbz9bFyMUhJLCUUeLPyv1MIAkhgSYmiUMLFUFsNgFDia63XWwg toiAk8TCWX/ZQRqYBVqYJRqfNLCAJIQFLCXuzP0PZrMIqEq0vDzBDGLzCnhIbJq8ggVim5zE /5crwBZwCnhK/Pt7igVimYfEs0M9zBMYeRcwMqxiFE0tTS4oTkrPNdQrTswtLs1L10vOz93E CAm9LzsYFx+zOsQowMGoxMN709AlXIg1say4MvcQowQHs5IIb30YUIg3JbGyKrUoP76oNCe1 +BCjNAeLkjjv3F3vQ4QE0hNLUrNTUwtSi2CyTBycUg2M/amnVi/5djl2r3DZqR8Hrgg7Oxe6 OmWdNv0XovzyxB33XmHjTJnZxSzqh1mzFT2SuyXiLbyCHB+8MhPZcvbeHom+hLdJ3FwB2z5t PR9p/50nafXVhT0XC9yXXFras1dRI/xXxLfjFwMy/mdUrmGMd8u5afj28scJnuYrXD+zzN/y tldtbt8XJZbijERDLeai4kQADNap1jkCAAA= Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds support for IOMMU to s5p-mfc device driver. MFC firmware is limited and it cannot use the default configuration. If IOMMU is available, the patch disables the default DMA address space configuration and creates a new address space of size limited to 256M and base address set to 0x20000000. For now the same address space is shared by both 'left' and 'right' memory channels, because the DMA/IOMMU frameworks do not support configuring them separately. This is not optimal, but besides limiting total address space available has no other drawbacks (MFC firmware supports 256M of address space per each channel). Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 24 ++++++++ drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h | 79 ++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index fff5f43..6ee620e 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -30,6 +30,7 @@ #include "s5p_mfc_dec.h" #include "s5p_mfc_enc.h" #include "s5p_mfc_intr.h" +#include "s5p_mfc_iommu.h" #include "s5p_mfc_opr.h" #include "s5p_mfc_cmd.h" #include "s5p_mfc_pm.h" @@ -1084,6 +1085,22 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) struct device *dev = &mfc_dev->plat_dev->dev; /* + * When IOMMU is available, we cannot use the default configuration, + * because of MFC firmware requirements: address space limited to + * 256M and non-zero default start address. + * This is still simplified, not optimal configuration, but for now + * IOMMU core doesn't allow to configure device's IOMMUs channel + * separately. + */ + if (exynos_is_iommu_available(dev)) { + int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, + S5P_MFC_IOMMU_DMA_SIZE); + if (ret == 0) + mfc_dev->mem_dev_l = mfc_dev->mem_dev_r = dev; + return ret; + } + + /* * Create and initialize virtual devices for accessing * reserved memory regions. */ @@ -1103,6 +1120,13 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) { + struct device *dev = &mfc_dev->plat_dev->dev; + + if (exynos_is_iommu_available(dev)) { + exynos_unconfigure_iommu(dev); + return; + } + device_unregister(mfc_dev->mem_dev_l); device_unregister(mfc_dev->mem_dev_r); } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h new file mode 100644 index 0000000..5d1d1c2 --- /dev/null +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co.Ltd + * Authors: Marek Szyprowski + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef S5P_MFC_IOMMU_H_ +#define S5P_MFC_IOMMU_H_ + +#define S5P_MFC_IOMMU_DMA_BASE 0x20000000lu +#define S5P_MFC_IOMMU_DMA_SIZE SZ_256M + +#ifdef CONFIG_EXYNOS_IOMMU + +#include + +static inline bool exynos_is_iommu_available(struct device *dev) +{ + return dev->archdata.iommu != NULL; +} + +static inline void exynos_unconfigure_iommu(struct device *dev) +{ + struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev); + + arm_iommu_detach_device(dev); + arm_iommu_release_mapping(mapping); +} + +static inline int exynos_configure_iommu(struct device *dev, + unsigned int base, unsigned int size) +{ + struct dma_iommu_mapping *mapping = NULL; + int ret; + + /* Disable the default mapping created by device core */ + if (to_dma_iommu_mapping(dev)) + exynos_unconfigure_iommu(dev); + + mapping = arm_iommu_create_mapping(dev->bus, base, size); + if (IS_ERR(mapping)) { + pr_warn("Failed to create IOMMU mapping for device %s\n", + dev_name(dev)); + return PTR_ERR(mapping); + } + + ret = arm_iommu_attach_device(dev, mapping); + if (ret) { + pr_warn("Failed to attached device %s to IOMMU_mapping\n", + dev_name(dev)); + arm_iommu_release_mapping(mapping); + return ret; + } + + return 0; +} + +#else + +static inline bool exynos_is_iommu_available(struct device *dev) +{ + return false; +} + +static inline int exynos_configure_iommu(struct device *dev, + unsigned int base, unsigned int size) +{ + return -ENOSYS; +} + +static inline void exynos_unconfigure_iommu(struct device *dev) { } + +#endif + +#endif /* S5P_MFC_IOMMU_H_ */