From patchwork Mon Dec 7 12:09:02 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 7783031 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 1E8FABEEE1 for ; Mon, 7 Dec 2015 12:10:03 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 33143203B1 for ; Mon, 7 Dec 2015 12:10:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 30E3F2040F for ; Mon, 7 Dec 2015 12:10:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755335AbbLGMJr (ORCPT ); Mon, 7 Dec 2015 07:09:47 -0500 Received: from mailout3.w1.samsung.com ([210.118.77.13]:21732 "EHLO mailout3.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755051AbbLGMJo (ORCPT ); Mon, 7 Dec 2015 07:09:44 -0500 Received: from eucpsbgm2.samsung.com (unknown [203.254.199.245]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0NYZ00MKILS3A5A0@mailout3.w1.samsung.com>; Mon, 07 Dec 2015 12:09:39 +0000 (GMT) X-AuditID: cbfec7f5-f79b16d000005389-94-566577035a26 Received: from eusync1.samsung.com ( [203.254.199.211]) by eucpsbgm2.samsung.com (EUCPMTA) with SMTP id 10.F3.21385.30775665; Mon, 7 Dec 2015 12:09:39 +0000 (GMT) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0NYZ00FEQLRTAS00@eusync1.samsung.com>; Mon, 07 Dec 2015 12:09:39 +0000 (GMT) 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 , Laurent Pinchart , Andrzej Hajda , Kukjin Kim , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz Subject: [PATCH 7/7] media: s5p-mfc: add iommu support Date: Mon, 07 Dec 2015 13:09:02 +0100 Message-id: <1449490142-27502-8-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <1449490142-27502-1-git-send-email-m.szyprowski@samsung.com> References: <1449490142-27502-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrILMWRmVeSWpSXmKPExsVy+t/xy7rM5alhBicuKljcWneO1WLjjPWs FvOPAFk/Xl9gs3j9wtCi//FrZovOiUvYLXo2bGW1mHF+H5PF2iN32S0Ov2lndeD2mN0xk9Vj 06pONo++LasYPT5vkgtgieKySUnNySxLLdK3S+DKONo0g7HgqVrFutm/GBsYZyl0MXJwSAiY SNxpiOhi5AQyxSQu3FvP1sXIxSEksJRRYt6kHawQThOTxN7Z05hAqtgEDCW63naxgdgiAk4S C2f9ZQcpYhboYJZ4MHMhK0hCWMBMYtbZR2ANLAKqEnv7GsFsXgEPid7ZnawQ6+Qk/r9cARbn FPCUePjzOyPIRUJANY+3ZExg5F3AyLCKUTS1NLmgOCk910ivODG3uDQvXS85P3cTIyTgvu5g XHrM6hCjAAejEg/vhMyUMCHWxLLiytxDjBIczEoivLKZqWFCvCmJlVWpRfnxRaU5qcWHGKU5 WJTEeWfueh8iJJCeWJKanZpakFoEk2Xi4JRqYEy9o+B3ZQE/Q7r1a/7MdX8vRDrFWPfv2vez YTlzP6PYzku8C9w1WNmsWxa1aMinaK5l4ztsXKKadtzp/TJx8Tny3BcSWDapbGW9UrLQw6lr +ecttUaX1x+Ss/zvlnFI6K1CYfwMIyPGbd2X68yVUm+s137yUj7HnMfygsvam9tUZJb+uKy/ WYmlOCPRUIu5qDgRADpBzxk0AgAA Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.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 --- 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 55c557f835f2..dfbaadd22a3d 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" @@ -1082,6 +1083,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. */ @@ -1099,6 +1116,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 000000000000..5d1d1c2922e8 --- /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_ */