From nobody Tue Jun 16 01:18:29 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2D88B31715C; Wed, 15 Apr 2026 07:23:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776237838; cv=none; b=h0WqGfMnPHXhScGJQDid76KGKP1qq/Fp60rNmTDhsxoigTQAkxkJWiJE4z0SfULRY4CKO/cUlVtJ9Le5eL1XRwNbP/oOHC1nhazpTTS2PA6dHxEHVjW2as9A5g+F5DfIO6wv750WfOpkKAgjyCvN32I7rLeRPZp/te8wQts1UR0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776237838; c=relaxed/simple; bh=8xvsn+jlVFtEMiQtA9C/Ao3q3yPX51zlgfCHv14LOWY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FHRRBiB0NhXb+dMwX1UcdiIMMDRhJeoY5o9+1Y1JwpfY9lbPJZT357Bc4cXT78vwZIHEhgptMMiP6EaKYBwtiq53oaVJr+Lcn/1UzgoAO9GqrMuYYZPnFJUscpivtXgHoxuwevPz788X3WnKapa6OT2+egelv8ytqKGbG8ZDgms= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=bdmay8HF; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="bdmay8HF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1776237835; bh=8xvsn+jlVFtEMiQtA9C/Ao3q3yPX51zlgfCHv14LOWY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bdmay8HFjz5HNg6PH1QWH0WKOpCgnsegKR+Fo00JO3BRCG0yfuBX5GUxYs6oGOKF6 Fz8AP/wkbziKAjB1ngLhMKoz9KlhZXtwrspfc4winkC6JhrQ02oo6eDozUWr13oVKI ULU9jD0EAPpaDB5+F/y8uornUbNa6inl3YsgxNaXOoFvcXFjukLgxmRtIXGn8E1p/t fk9X9oPgk07faQLx9kqeekiY0qEJeTiJ6ziRSNKG3HloZN6VDHIE4Apg5glmmXDl2f 0/gCfv7IyxSVOnL16DuN892p9BzOqQMGhNH9qCA7kzlSvYJ5jbOf8BlvNpkj3YpsXX BQfbXCfOCC48Q== Received: from benjamin-XPS-13-9310.. (unknown [100.64.1.43]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: benjamin.gaignard) by bali.collaboradmins.com (Postfix) with ESMTPSA id 469BB17E1340; Wed, 15 Apr 2026 09:23:55 +0200 (CEST) From: Benjamin Gaignard To: joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, krzk+dt@kernel.org, conor+dt@kernel.org, heiko@sntech.de Cc: iommu@lists.linux.dev, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, kernel@collabora.com, Benjamin Gaignard , Conor Dooley Subject: [PATCH v14 1/5] dt-bindings: vendor-prefixes: Add Verisilicon Date: Wed, 15 Apr 2026 09:23:37 +0200 Message-ID: <20260415072349.44237-2-benjamin.gaignard@collabora.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260415072349.44237-1-benjamin.gaignard@collabora.com> References: <20260415072349.44237-1-benjamin.gaignard@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Verisilicon Microelectronics is a company based in Shanghai, China, developping hardware blocks for SoC. https://verisilicon.com/ Add their name to the list of vendors. Signed-off-by: Benjamin Gaignard Acked-by: Conor Dooley --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Docum= entation/devicetree/bindings/vendor-prefixes.yaml index ee7fd3cfe203..ebd9072300a8 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -1761,6 +1761,8 @@ patternProperties: description: Variscite Ltd. "^vdl,.*": description: Van der Laan b.v. + "^verisilicon,.*": + description: VeriSilicon Microelectronics "^vertexcom,.*": description: Vertexcom Technologies, Inc. "^via,.*": --=20 2.43.0 From nobody Tue Jun 16 01:18:29 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A53463A1CF3; Wed, 15 Apr 2026 07:23:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776237839; cv=none; b=X9a1c1BWxMwpbu24906aPZCjLg1FBRVClKY7kpunJQYaBneoLlSe7tuQxzy3aUf4iALRSQYRtNQAKy2BdCLPSMSu3GFWdu3NXNgtkbj6vN8ulUy/5hNckuzTtIkeU60IhaDeOnXu+jvy0k02a/AC85yVVYqMdn57BWAwf+AbES4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776237839; c=relaxed/simple; bh=heh+k/1ODoaxXv2R5HPjXJm6oybJcbQZVD3EyshC35g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hnKOEDGARPM1cq1YVK5luR8q0pG5L+wckvE8Igbehy1izcKz9j2TVZ+Kb7RCxSDPwH9nJQr/oZJsVcREybEPOmIRCUG+/alEvcezDuym5tQfXuGbzxwbY2PBWSW5i83Gwj646XIVBNfOaMSfqYcB4Op9OxiIgVy6wHCtorl/Aq0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=gqFkTqn8; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="gqFkTqn8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1776237836; bh=heh+k/1ODoaxXv2R5HPjXJm6oybJcbQZVD3EyshC35g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gqFkTqn8z0pK8YA+xdWK7PRnq5dHuDZun6hNKMP5Vpodvz4+hg8pmvuWXRiCgLZQ8 gmxZl/tsEgP3zWx5Yz35yrxsg4nCRTiH6hAz43Ek+PLb2k7tOt46g8m6hhGY3g4evm z1LOSkyjgQonwd54Ltb3cdRKqKa7AzZorS8I6Bas+MUyk5/dRYJILTwotJb5ZDOyCp 8Qm0U+Xny7rP/FGV7KACu6BtbNoWG7tfVhIa7zCPkalZ7oWr++bpd+jpLNZMdzj3cs Xwv/fFTYlRG3ZZ/JXni+iGiJUvqh2UKldqobnID+CVh4ivdanRXG2yo9BpIOMZhrMy hgBACg16oykUw== Received: from benjamin-XPS-13-9310.. (unknown [100.64.1.43]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: benjamin.gaignard) by bali.collaboradmins.com (Postfix) with ESMTPSA id C70A017E1388; Wed, 15 Apr 2026 09:23:55 +0200 (CEST) From: Benjamin Gaignard To: joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, krzk+dt@kernel.org, conor+dt@kernel.org, heiko@sntech.de Cc: iommu@lists.linux.dev, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, kernel@collabora.com, Benjamin Gaignard , Conor Dooley Subject: [PATCH v14 2/5] dt-bindings: iommu: verisilicon: Add binding for VSI IOMMU Date: Wed, 15 Apr 2026 09:23:38 +0200 Message-ID: <20260415072349.44237-3-benjamin.gaignard@collabora.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260415072349.44237-1-benjamin.gaignard@collabora.com> References: <20260415072349.44237-1-benjamin.gaignard@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a device tree binding for the Verisilicon (VSI) IOMMU. This IOMMU sits in front of hardware encoder and decoder blocks on SoCs using Verisilicon IP, such as the Rockchip RK3588. Signed-off-by: Benjamin Gaignard Reviewed-by: Conor Dooley --- .../bindings/iommu/verisilicon,iommu.yaml | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 Documentation/devicetree/bindings/iommu/verisilicon,iom= mu.yaml diff --git a/Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml= b/Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml new file mode 100644 index 000000000000..d3ce9e603b61 --- /dev/null +++ b/Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iommu/verisilicon,iommu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Verisilicon IOMMU + +maintainers: + - Benjamin Gaignard + +description: |+ + A Versilicon iommu translates io virtual addresses to physical addresses= for + its associated video decoder. + +properties: + compatible: + items: + - const: rockchip,rk3588-av1-iommu + - const: verisilicon,iommu-1.2 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Core clock + - description: Interface clock + + clock-names: + items: + - const: core + - const: iface + + "#iommu-cells": + const: 0 + + power-domains: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - "#iommu-cells" + +additionalProperties: false + +examples: + - | + #include + #include + + bus { + #address-cells =3D <2>; + #size-cells =3D <2>; + + iommu@fdca0000 { + compatible =3D "rockchip,rk3588-av1-iommu","verisilicon,iommu-1.2"; + reg =3D <0x0 0xfdca0000 0x0 0x600>; + interrupts =3D ; + clocks =3D <&cru ACLK_AV1>, <&cru PCLK_AV1>; + clock-names =3D "core", "iface"; + #iommu-cells =3D <0>; + }; + }; --=20 2.43.0 From nobody Tue Jun 16 01:18:29 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 32AD93A254C; Wed, 15 Apr 2026 07:23:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776237840; cv=none; b=qrsjCyfLTUVLLsrZbzDpZPv6pMKzBlbwMBp4CnlWsB2a9XuWjFJbFLtCXmA0JgIpL76BUx6BNUd9hSad0CqrHglqla3wEJj7n0R6BYy+FhbpDMeAVzI5p4+f+R+RcQqXuj3vIm78CU546fAfo69b0K4GhW+lqxGcQB8AZjKQhb0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776237840; c=relaxed/simple; bh=HBdUDjhkORFuHPMw9QPRPpfuvZwVBvMsWnynL4zYMqA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uELbHpbAqchcSoD5txBYrLYUADQN3NuNrWzISOWuO4UoIjr+a8vNUobyzXcxGTLYam1yYUzhyeQfoMwpEHbW3Fd2l17USnVji6VG3ys5+OwAGVhgQJBejyAszAVUd4FzjL6hCMjI8wwDp4urW8eKyLr/VCAl5NwsSLuc3zi2/Ks= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=lahq6krD; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="lahq6krD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1776237836; bh=HBdUDjhkORFuHPMw9QPRPpfuvZwVBvMsWnynL4zYMqA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lahq6krDFOrsXvD2nPrflmz1Cfs5LgFcvG4eHgmbZajuQzHQ21IMrzKbLQoa4Vnab epuVLjEWA/+2KBM0QWUW99TIaQ91jQXNIcYxhLSTMzLLKYjMAQyjY88cWFryyn8ocS zS6sF/Hkg+YF/bEA9DgUqzKC7/aje2GxBOLShb7S41c2B9XgeGfDE7A4awTuqzZ5Bs ypzig24CPD8zeoZReyhoJEG6UckWA+bHYHWtvhHbRFCCFxYuJ8E8VyfAdzXiZydiam bMwSIGWZuZYA+qRmEw8iCVhmRqG7UuvO9FnmWmzV29MvBVaDe3JQa0/086WyI6sT2z 3zHVPUWHnuX/A== Received: from benjamin-XPS-13-9310.. (unknown [100.64.1.43]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: benjamin.gaignard) by bali.collaboradmins.com (Postfix) with ESMTPSA id 5336617E141B; Wed, 15 Apr 2026 09:23:56 +0200 (CEST) From: Benjamin Gaignard To: joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, krzk+dt@kernel.org, conor+dt@kernel.org, heiko@sntech.de Cc: iommu@lists.linux.dev, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, kernel@collabora.com, Benjamin Gaignard Subject: [PATCH v14 3/5] iommu: Add verisilicon IOMMU driver Date: Wed, 15 Apr 2026 09:23:39 +0200 Message-ID: <20260415072349.44237-4-benjamin.gaignard@collabora.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260415072349.44237-1-benjamin.gaignard@collabora.com> References: <20260415072349.44237-1-benjamin.gaignard@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The Verisilicon IOMMU hardware block can be found in combination with Verisilicon hardware video codecs (encoders or decoders) on different SoCs. Enable it will allow us to use non contiguous memory allocators for Verisilicon video codecs. Signed-off-by: Benjamin Gaignard --- changes in version 14: - Flush TLB after each map/unmap operations. - Remove vsi_iommu_restore_ctx() and do not touch Verisilicon stateless video decoder. - Allow to build the driver as a module. MAINTAINERS | 8 + drivers/iommu/Kconfig | 11 + drivers/iommu/Makefile | 1 + drivers/iommu/vsi-iommu.c | 796 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 816 insertions(+) create mode 100644 drivers/iommu/vsi-iommu.c diff --git a/MAINTAINERS b/MAINTAINERS index c3fe46d7c4bc..fa56dd0e3f25 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -27667,6 +27667,14 @@ F: drivers/media/v4l2-core/v4l2-isp.c F: include/media/v4l2-isp.h F: include/uapi/linux/media/v4l2-isp.h =20 +VERISILICON IOMMU DRIVER +M: Benjamin Gaignard +L: iommu@lists.linux.dev +S: Maintained +F: Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml +F: drivers/iommu/vsi-iommu.c +F: include/linux/vsi-iommu.h + VF610 NAND DRIVER M: Stefan Agner L: linux-mtd@lists.infradead.org diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index f86262b11416..18d3d68af7cd 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -384,6 +384,17 @@ config SPRD_IOMMU =20 Say Y here if you want to use the multimedia devices listed above. =20 +config VSI_IOMMU + tristate "Verisilicon IOMMU Support" + depends on (ARCH_ROCKCHIP && ARM64) || COMPILE_TEST + select IOMMU_API + help + Support for IOMMUs used by Verisilicon sub-systems like video + decoders or encoder hardware blocks. + + Say Y here if you want to use this IOMMU in front of these + hardware blocks. + config IOMMU_DEBUG_PAGEALLOC bool "Debug IOMMU mappings against page allocations" depends on DEBUG_PAGEALLOC && IOMMU_API && PAGE_EXTENSION diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 0275821f4ef9..887af357a7c9 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -36,4 +36,5 @@ obj-$(CONFIG_IOMMU_SVA) +=3D iommu-sva.o obj-$(CONFIG_IOMMU_IOPF) +=3D io-pgfault.o obj-$(CONFIG_SPRD_IOMMU) +=3D sprd-iommu.o obj-$(CONFIG_APPLE_DART) +=3D apple-dart.o +obj-$(CONFIG_VSI_IOMMU) +=3D vsi-iommu.o obj-$(CONFIG_IOMMU_DEBUG_PAGEALLOC) +=3D iommu-debug-pagealloc.o diff --git a/drivers/iommu/vsi-iommu.c b/drivers/iommu/vsi-iommu.c new file mode 100644 index 000000000000..5d0721bd2c7a --- /dev/null +++ b/drivers/iommu/vsi-iommu.c @@ -0,0 +1,796 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (C) 2025 Collabora Ltd. + * + * IOMMU API for Verisilicon + * + * Module Authors: Yandong Lin + * Simon Xue + * Benjamin Gaignard + * + * This hardware block is using a 2 pages tables allocation structure. + * That make very similar to Rockhip iommu hardware blocks but it has + * it own driver because the registers offset and configuration bits + * are completely different. An additional reason is that this hardware + * has been developed by Verisilicon to be used by their hardware video + * decoders and not for a general purpose like Rockchip iommus. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iommu-pages.h" + +struct vsi_iommu { + struct device *dev; + void __iomem *regs; + struct clk_bulk_data *clocks; + int num_clocks; + struct iommu_device iommu; + struct list_head node; /* entry in vsi_iommu_domain.iommus */ + struct iommu_domain *domain; /* domain to which iommu is attached */ + spinlock_t lock; /* lock to protect vsi_iommu fields */ + int irq; + bool enable; +}; + +struct vsi_iommu_domain { + struct list_head iommus; + struct device *dev; + u32 *dt; + dma_addr_t dt_dma; + struct iommu_domain domain; + u64 *pta; + dma_addr_t pta_dma; + spinlock_t lock; /* lock to protect vsi_iommu_domain fields */ +}; + +static struct iommu_domain vsi_identity_domain; + +#define NUM_DT_ENTRIES 1024 +#define NUM_PT_ENTRIES 1024 + +#define SPAGE_SIZE BIT(12) + +/* vsi iommu regs address */ +#define VSI_MMU_CONFIG1_BASE 0x1ac +#define VSI_MMU_AHB_EXCEPTION_BASE 0x380 +#define VSI_MMU_AHB_CONTROL_BASE 0x388 +#define VSI_MMU_AHB_TLB_ARRAY_BASE_L_BASE 0x38C + +/* MMU register offsets */ +#define VSI_MMU_FLUSH_BASE 0x184 +#define VSI_MMU_BIT_FLUSH BIT(4) + +#define VSI_MMU_PAGE_FAULT_ADDR 0x380 +#define VSI_MMU_STATUS_BASE 0x384 /* IRQ status */ + +#define VSI_MMU_BIT_ENABLE BIT(0) + +#define VSI_MMU_OUT_OF_BOUND BIT(28) +/* Irq mask */ +#define VSI_MMU_IRQ_MASK 0x7 + +#define VSI_DTE_PT_ADDRESS_MASK 0xffffffc0 +#define VSI_DTE_PT_VALID BIT(0) + +#define VSI_PAGE_DESC_LO_MASK 0xfffff000 +#define VSI_PAGE_DESC_HI_MASK GENMASK_ULL(39, 32) +#define VSI_PAGE_DESC_HI_SHIFT (32 - 4) + +static inline phys_addr_t vsi_dte_pt_address(u32 dte) +{ + return (phys_addr_t)dte & VSI_DTE_PT_ADDRESS_MASK; +} + +static inline u32 vsi_mk_dte(u32 dte) +{ + return (phys_addr_t)dte | VSI_DTE_PT_VALID; +} + +#define VSI_PTE_PAGE_WRITABLE BIT(2) +#define VSI_PTE_PAGE_VALID BIT(0) + +static inline phys_addr_t vsi_pte_page_address(u64 pte) +{ + return ((pte << VSI_PAGE_DESC_HI_SHIFT) & VSI_PAGE_DESC_HI_MASK) | + (pte & VSI_PAGE_DESC_LO_MASK); +} + +static u32 vsi_mk_pte(phys_addr_t page, int prot) +{ + u32 flags =3D 0; + + flags |=3D (prot & IOMMU_WRITE) ? VSI_PTE_PAGE_WRITABLE : 0; + + page =3D (page & VSI_PAGE_DESC_LO_MASK) | + ((page & VSI_PAGE_DESC_HI_MASK) >> VSI_PAGE_DESC_HI_SHIFT); + + return page | flags | VSI_PTE_PAGE_VALID; +} + +#define VSI_DTE_PT_VALID BIT(0) + +static inline bool vsi_dte_is_pt_valid(u32 dte) +{ + return dte & VSI_DTE_PT_VALID; +} + +static inline bool vsi_pte_is_page_valid(u32 pte) +{ + return pte & VSI_PTE_PAGE_VALID; +} + +static u32 vsi_mk_pte_invalid(u32 pte) +{ + return pte & ~VSI_PTE_PAGE_VALID; +} + +#define VSI_MASTER_TLB_MASK GENMASK_ULL(31, 10) +/* mode 0 : 4k */ +#define VSI_PTA_4K_MODE 0 + +static u64 vsi_mk_pta(dma_addr_t dt_dma) +{ + u64 val =3D (dt_dma & VSI_MASTER_TLB_MASK) | VSI_PTA_4K_MODE; + + return val; +} + +static struct vsi_iommu_domain *to_vsi_domain(struct iommu_domain *dom) +{ + return container_of(dom, struct vsi_iommu_domain, domain); +} + +static inline void vsi_table_flush(struct vsi_iommu_domain *vsi_domain, dm= a_addr_t dma, + unsigned int count) +{ + size_t size =3D count * sizeof(u32); /* count of u32 entry */ + + dma_sync_single_for_device(vsi_domain->dev, dma, size, DMA_TO_DEVICE); +} + +#define VSI_IOVA_DTE_MASK 0xffc00000 +#define VSI_IOVA_DTE_SHIFT 22 +#define VSI_IOVA_PTE_MASK 0x003ff000 +#define VSI_IOVA_PTE_SHIFT 12 +#define VSI_IOVA_PAGE_MASK 0x00000fff +#define VSI_IOVA_PAGE_SHIFT 0 + +static u32 vsi_iova_dte_index(u32 iova) +{ + return (iova & VSI_IOVA_DTE_MASK) >> VSI_IOVA_DTE_SHIFT; +} + +static u32 vsi_iova_pte_index(u32 iova) +{ + return (iova & VSI_IOVA_PTE_MASK) >> VSI_IOVA_PTE_SHIFT; +} + +static u32 vsi_iova_page_offset(u32 iova) +{ + return (iova & VSI_IOVA_PAGE_MASK) >> VSI_IOVA_PAGE_SHIFT; +} + +static irqreturn_t vsi_iommu_irq(int irq, void *dev_id) +{ + struct vsi_iommu *iommu =3D dev_id; + unsigned long flags; + dma_addr_t iova; + u32 status; + + if (pm_runtime_resume_and_get(iommu->dev) < 0) + return IRQ_NONE; + + spin_lock_irqsave(&iommu->lock, flags); + + status =3D readl(iommu->regs + VSI_MMU_STATUS_BASE); + if (status & VSI_MMU_IRQ_MASK) { + dev_err(iommu->dev, "unexpected int_status=3D%08x\n", status); + iova =3D readl(iommu->regs + VSI_MMU_PAGE_FAULT_ADDR); + report_iommu_fault(iommu->domain, iommu->dev, iova, status); + } + writel(0, iommu->regs + VSI_MMU_STATUS_BASE); + + spin_unlock_irqrestore(&iommu->lock, flags); + pm_runtime_put_autosuspend(iommu->dev); + + return IRQ_HANDLED; +} + +static struct vsi_iommu *vsi_iommu_get_from_dev(struct device *dev) +{ + struct iommu_fwspec *fwspec =3D dev_iommu_fwspec_get(dev); + struct device *iommu_dev =3D bus_find_device_by_fwnode(&platform_bus_type, + fwspec->iommu_fwnode); + + put_device(iommu_dev); + + return iommu_dev ? dev_get_drvdata(iommu_dev) : NULL; +} + +static struct iommu_domain *vsi_iommu_domain_alloc_paging(struct device *d= ev) +{ + struct vsi_iommu *iommu =3D dev_iommu_priv_get(dev); + struct vsi_iommu_domain *vsi_domain; + + vsi_domain =3D kzalloc(sizeof(*vsi_domain), GFP_KERNEL); + if (!vsi_domain) + return NULL; + + vsi_domain->dev =3D iommu->dev; + spin_lock_init(&vsi_domain->lock); + + /* + * iommu use a 2 level pagetable. + * Each level1 (dt) and level2 (pt) table has 1024 4-byte entries. + * Allocate one 4 KiB page for each table. + */ + vsi_domain->dt =3D iommu_alloc_pages_sz(GFP_KERNEL | GFP_DMA32, + SPAGE_SIZE); + if (!vsi_domain->dt) + goto err_free_domain; + + vsi_domain->dt_dma =3D dma_map_single(vsi_domain->dev, vsi_domain->dt, + SPAGE_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(vsi_domain->dev, vsi_domain->dt_dma)) { + dev_err(dev, "DMA map error for DT\n"); + goto err_free_dt; + } + + vsi_domain->pta =3D iommu_alloc_pages_sz(GFP_KERNEL | GFP_DMA32, + SPAGE_SIZE); + if (!vsi_domain->pta) + goto err_unmap_dt; + + vsi_domain->pta[0] =3D vsi_mk_pta(vsi_domain->dt_dma); + vsi_domain->pta_dma =3D dma_map_single(vsi_domain->dev, vsi_domain->pta, + SPAGE_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(vsi_domain->dev, vsi_domain->pta_dma)) { + dev_err(dev, "DMA map error for PTA\n"); + goto err_free_pta; + } + + INIT_LIST_HEAD(&vsi_domain->iommus); + + vsi_domain->domain.geometry.aperture_start =3D 0; + vsi_domain->domain.geometry.aperture_end =3D DMA_BIT_MASK(32); + vsi_domain->domain.geometry.force_aperture =3D true; + vsi_domain->domain.pgsize_bitmap =3D SZ_4K; + + return &vsi_domain->domain; + +err_free_pta: + iommu_free_pages(vsi_domain->pta); +err_unmap_dt: + dma_unmap_single(vsi_domain->dev, vsi_domain->dt_dma, + SPAGE_SIZE, DMA_TO_DEVICE); +err_free_dt: + iommu_free_pages(vsi_domain->dt); +err_free_domain: + kfree(vsi_domain); + + return NULL; +} + +static phys_addr_t vsi_iommu_iova_to_phys(struct iommu_domain *domain, + dma_addr_t iova) +{ + struct vsi_iommu_domain *vsi_domain =3D to_vsi_domain(domain); + phys_addr_t pt_phys, phys =3D 0; + unsigned long flags; + u32 dte, pte; + u32 *page_table; + + spin_lock_irqsave(&vsi_domain->lock, flags); + dte =3D vsi_domain->dt[vsi_iova_dte_index(iova)]; + if (!vsi_dte_is_pt_valid(dte)) + goto unlock; + + pt_phys =3D vsi_dte_pt_address(dte); + page_table =3D (u32 *)phys_to_virt(pt_phys); + pte =3D page_table[vsi_iova_pte_index(iova)]; + if (!vsi_pte_is_page_valid(pte)) + goto unlock; + + phys =3D vsi_pte_page_address(pte) + vsi_iova_page_offset(iova); + +unlock: + spin_unlock_irqrestore(&vsi_domain->lock, flags); + return phys; +} + +static size_t vsi_iommu_unmap_iova(struct vsi_iommu_domain *vsi_domain, + u32 *pte_addr, dma_addr_t pte_dma, + size_t size) +{ + unsigned int pte_count; + unsigned int pte_total =3D size / SPAGE_SIZE; + + for (pte_count =3D 0; + pte_count < pte_total && pte_count < NUM_PT_ENTRIES; pte_count++) { + u32 pte =3D pte_addr[pte_count]; + + if (!vsi_pte_is_page_valid(pte)) + break; + + pte_addr[pte_count] =3D vsi_mk_pte_invalid(pte); + } + + vsi_table_flush(vsi_domain, pte_dma, pte_total); + + return pte_count * SPAGE_SIZE; +} + +static int vsi_iommu_map_iova(struct vsi_iommu_domain *vsi_domain, u32 *pt= e_addr, + dma_addr_t pte_dma, dma_addr_t iova, + phys_addr_t paddr, size_t size, int prot) +{ + unsigned int pte_count; + unsigned int pte_total =3D size / SPAGE_SIZE; + + for (pte_count =3D 0; + pte_count < pte_total && pte_count < NUM_PT_ENTRIES; pte_count++) { + u32 pte =3D pte_addr[pte_count]; + + if (vsi_pte_is_page_valid(pte)) + return (pte_count - 1) * SPAGE_SIZE; + + pte_addr[pte_count] =3D vsi_mk_pte(paddr, prot); + + paddr +=3D SPAGE_SIZE; + } + + vsi_table_flush(vsi_domain, pte_dma, pte_total); + + return 0; +} + +static void vsi_iommu_flush_tlb(struct iommu_domain *domain) +{ + struct vsi_iommu_domain *vsi_domain =3D to_vsi_domain(domain); + struct list_head *pos; + + list_for_each(pos, &vsi_domain->iommus) { + struct vsi_iommu *iommu; + + iommu =3D list_entry(pos, struct vsi_iommu, node); + if (!iommu) + continue; + + if (pm_runtime_get(iommu->dev) < 0) + continue; + + spin_lock(&iommu->lock); + + if (iommu->enable) { + writel(VSI_MMU_BIT_FLUSH, iommu->regs + VSI_MMU_FLUSH_BASE); + writel(0, iommu->regs + VSI_MMU_FLUSH_BASE); + } + + spin_unlock(&iommu->lock); + + pm_runtime_put_autosuspend(iommu->dev); + } +} + +static size_t vsi_iommu_unmap(struct iommu_domain *domain, unsigned long _= iova, + size_t size, size_t count, struct iommu_iotlb_gather *gather) +{ + struct vsi_iommu_domain *vsi_domain =3D to_vsi_domain(domain); + dma_addr_t pte_dma, iova =3D (dma_addr_t)_iova; + unsigned long flags; + phys_addr_t pt_phys; + u32 dte; + u32 *pte_addr; + size_t unmap_size =3D 0; + + spin_lock_irqsave(&vsi_domain->lock, flags); + + dte =3D vsi_domain->dt[vsi_iova_dte_index(iova)]; + /* Just return 0 if iova is unmapped */ + if (!vsi_dte_is_pt_valid(dte)) + goto unlock; + + pt_phys =3D vsi_dte_pt_address(dte); + pte_addr =3D (u32 *)phys_to_virt(pt_phys) + vsi_iova_pte_index(iova); + pte_dma =3D pt_phys + vsi_iova_pte_index(iova) * sizeof(u32); + unmap_size =3D vsi_iommu_unmap_iova(vsi_domain, pte_addr, pte_dma, size); + if (!unmap_size) + goto unlock; + + vsi_iommu_flush_tlb(domain); +unlock: + spin_unlock_irqrestore(&vsi_domain->lock, flags); + + return unmap_size; +} + +static u32 *vsi_dte_get_page_table(struct vsi_iommu_domain *vsi_domain, + dma_addr_t iova, gfp_t gfp) +{ + u32 *page_table, *dte_addr; + u32 dte_index, dte; + phys_addr_t pt_phys; + dma_addr_t pt_dma; + gfp_t flags; + + dte_index =3D vsi_iova_dte_index(iova); + dte_addr =3D &vsi_domain->dt[dte_index]; + dte =3D *dte_addr; + if (vsi_dte_is_pt_valid(dte)) + goto done; + + /* Do not allow to sleep while allocating the buffer */ + flags =3D (gfp & ~GFP_KERNEL) | GFP_ATOMIC | GFP_DMA32; + page_table =3D iommu_alloc_pages_sz(flags, PAGE_SIZE); + if (!page_table) + return ERR_PTR(-ENOMEM); + + pt_dma =3D dma_map_single(vsi_domain->dev, page_table, PAGE_SIZE, DMA_TO_= DEVICE); + if (dma_mapping_error(vsi_domain->dev, pt_dma)) { + dev_err(vsi_domain->dev, "DMA mapping error while allocating page table\= n"); + iommu_free_pages(page_table); + return ERR_PTR(-ENOMEM); + } + + dte =3D vsi_mk_dte(pt_dma); + *dte_addr =3D dte; + + vsi_table_flush(vsi_domain, + vsi_domain->dt_dma + dte_index * sizeof(u32), 1); +done: + pt_phys =3D vsi_dte_pt_address(dte); + return (u32 *)phys_to_virt(pt_phys); +} + +static int vsi_iommu_map(struct iommu_domain *domain, unsigned long _iova, + phys_addr_t paddr, size_t size, size_t count, + int prot, gfp_t gfp, size_t *mapped) +{ + struct vsi_iommu_domain *vsi_domain =3D to_vsi_domain(domain); + dma_addr_t pte_dma, iova =3D (dma_addr_t)_iova; + u32 *page_table, *pte_addr; + u32 dte, pte_index; + unsigned long flags; + int ret; + + spin_lock_irqsave(&vsi_domain->lock, flags); + + page_table =3D vsi_dte_get_page_table(vsi_domain, iova, gfp); + if (IS_ERR(page_table)) { + spin_unlock_irqrestore(&vsi_domain->lock, flags); + return PTR_ERR(page_table); + } + + dte =3D vsi_domain->dt[vsi_iova_dte_index(iova)]; + pte_index =3D vsi_iova_pte_index(iova); + pte_addr =3D &page_table[pte_index]; + pte_dma =3D vsi_dte_pt_address(dte) + pte_index * sizeof(u32); + ret =3D vsi_iommu_map_iova(vsi_domain, pte_addr, pte_dma, iova, + paddr, size, prot); + if (!ret) + *mapped =3D size; + + vsi_iommu_flush_tlb(domain); + + spin_unlock_irqrestore(&vsi_domain->lock, flags); + + return ret; +} + +static void vsi_iommu_disable(struct vsi_iommu *iommu) +{ + writel(0, iommu->regs + VSI_MMU_AHB_CONTROL_BASE); + iommu->enable =3D false; +} + +static int vsi_iommu_identity_attach(struct iommu_domain *domain, + struct device *dev, struct iommu_domain *old) +{ + struct vsi_iommu *iommu =3D dev_iommu_priv_get(dev); + struct vsi_iommu_domain *vsi_domain =3D to_vsi_domain(domain); + unsigned long flags; + int ret; + + ret =3D pm_runtime_resume_and_get(iommu->dev); + if (ret < 0) + return ret; + + spin_lock_irqsave(&vsi_domain->lock, flags); + spin_lock(&iommu->lock); + if (iommu->domain =3D=3D domain) + goto unlock; + + vsi_iommu_disable(iommu); + list_del_init(&iommu->node); + + iommu->domain =3D domain; + +unlock: + spin_unlock(&iommu->lock); + spin_unlock_irqrestore(&vsi_domain->lock, flags); + pm_runtime_put_autosuspend(iommu->dev); + return 0; +} + +static const struct iommu_domain_ops vsi_identity_ops =3D { + .attach_dev =3D vsi_iommu_identity_attach, +}; + +static struct iommu_domain vsi_identity_domain =3D { + .type =3D IOMMU_DOMAIN_IDENTITY, + .ops =3D &vsi_identity_ops, +}; + +static void vsi_iommu_enable(struct vsi_iommu *iommu, struct iommu_domain = *domain) +{ + struct vsi_iommu_domain *vsi_domain =3D to_vsi_domain(domain); + + if (domain =3D=3D &vsi_identity_domain) + return; + + writel(vsi_domain->pta_dma, iommu->regs + VSI_MMU_AHB_TLB_ARRAY_BASE_L_BA= SE); + writel(VSI_MMU_OUT_OF_BOUND, iommu->regs + VSI_MMU_CONFIG1_BASE); + writel(VSI_MMU_BIT_ENABLE, iommu->regs + VSI_MMU_AHB_EXCEPTION_BASE); + writel(VSI_MMU_BIT_ENABLE, iommu->regs + VSI_MMU_AHB_CONTROL_BASE); + iommu->enable =3D true; +} + +static int vsi_iommu_attach_device(struct iommu_domain *domain, + struct device *dev, struct iommu_domain *old) +{ + struct vsi_iommu *iommu =3D dev_iommu_priv_get(dev); + struct vsi_iommu_domain *vsi_domain =3D to_vsi_domain(domain); + unsigned long flags; + int ret =3D 0; + + ret =3D pm_runtime_resume_and_get(iommu->dev); + if (ret < 0) + return ret; + + spin_lock_irqsave(&vsi_domain->lock, flags); + spin_lock(&iommu->lock); + + vsi_iommu_enable(iommu, domain); + writel(VSI_MMU_BIT_FLUSH, iommu->regs + VSI_MMU_FLUSH_BASE); + writel(0, iommu->regs + VSI_MMU_FLUSH_BASE); + + list_del_init(&iommu->node); + list_add_tail(&iommu->node, &vsi_domain->iommus); + + iommu->domain =3D domain; + + spin_unlock(&iommu->lock); + spin_unlock_irqrestore(&vsi_domain->lock, flags); + pm_runtime_put_autosuspend(iommu->dev); + return ret; +} + +static void vsi_iommu_domain_free(struct iommu_domain *domain) +{ + struct vsi_iommu_domain *vsi_domain =3D to_vsi_domain(domain); + unsigned long flags; + int i; + + spin_lock_irqsave(&vsi_domain->lock, flags); + + WARN_ON(!list_empty(&vsi_domain->iommus)); + + for (i =3D 0; i < NUM_DT_ENTRIES; i++) { + u32 dte =3D vsi_domain->dt[i]; + + if (vsi_dte_is_pt_valid(dte)) { + phys_addr_t pt_phys =3D vsi_dte_pt_address(dte); + u32 *page_table =3D phys_to_virt(pt_phys); + + dma_unmap_single(vsi_domain->dev, pt_phys, + SPAGE_SIZE, DMA_TO_DEVICE); + iommu_free_pages(page_table); + } + } + + dma_unmap_single(vsi_domain->dev, vsi_domain->dt_dma, + SPAGE_SIZE, DMA_TO_DEVICE); + iommu_free_pages(vsi_domain->dt); + + dma_unmap_single(vsi_domain->dev, vsi_domain->pta_dma, + SPAGE_SIZE, DMA_TO_DEVICE); + iommu_free_pages(vsi_domain->pta); + + spin_unlock_irqrestore(&vsi_domain->lock, flags); + + kfree(vsi_domain); +} + +static struct iommu_device *vsi_iommu_probe_device(struct device *dev) +{ + struct vsi_iommu *iommu =3D vsi_iommu_get_from_dev(dev); + struct device_link *link; + + link =3D device_link_add(dev, iommu->dev, + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); + if (!link) + dev_err(dev, "Unable to link %s\n", dev_name(iommu->dev)); + + dev_iommu_priv_set(dev, iommu); + return &iommu->iommu; +} + +static void vsi_iommu_release_device(struct device *dev) +{ + struct vsi_iommu *iommu =3D dev_iommu_priv_get(dev); + + device_link_remove(dev, iommu->dev); +} + +static int vsi_iommu_of_xlate(struct device *dev, const struct of_phandle_= args *args) +{ + return iommu_fwspec_add_ids(dev, args->args, 1); +} + +static const struct iommu_ops vsi_iommu_ops =3D { + .identity_domain =3D &vsi_identity_domain, + .release_domain =3D &vsi_identity_domain, + .domain_alloc_paging =3D vsi_iommu_domain_alloc_paging, + .of_xlate =3D vsi_iommu_of_xlate, + .probe_device =3D vsi_iommu_probe_device, + .release_device =3D vsi_iommu_release_device, + .device_group =3D generic_single_device_group, + .owner =3D THIS_MODULE, + .default_domain_ops =3D &(const struct iommu_domain_ops) { + .attach_dev =3D vsi_iommu_attach_device, + .map_pages =3D vsi_iommu_map, + .unmap_pages =3D vsi_iommu_unmap, + .iova_to_phys =3D vsi_iommu_iova_to_phys, + .free =3D vsi_iommu_domain_free, + } +}; + +static const struct of_device_id vsi_iommu_dt_ids[] =3D { + { + .compatible =3D "verisilicon,iommu-1.2", + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, vsi_iommu_dt_ids); + +static int vsi_iommu_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct vsi_iommu *iommu; + int err; + + iommu =3D devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL); + if (!iommu) + return -ENOMEM; + + iommu->dev =3D dev; + spin_lock_init(&iommu->lock); + INIT_LIST_HEAD(&iommu->node); + + iommu->regs =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(iommu->regs)) + return -ENOMEM; + + iommu->num_clocks =3D devm_clk_bulk_get_all(dev, &iommu->clocks); + if (iommu->num_clocks < 0) + return iommu->num_clocks; + + err =3D clk_bulk_prepare(iommu->num_clocks, iommu->clocks); + if (err) + return err; + + iommu->irq =3D platform_get_irq(pdev, 0); + if (iommu->irq < 0) + return iommu->irq; + + err =3D devm_request_irq(iommu->dev, iommu->irq, vsi_iommu_irq, + IRQF_SHARED, dev_name(dev), iommu); + if (err) + goto err_unprepare_clocks; + + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + platform_set_drvdata(pdev, iommu); + + pm_runtime_set_autosuspend_delay(dev, 100); + pm_runtime_use_autosuspend(dev); + pm_runtime_enable(dev); + + err =3D iommu_device_sysfs_add(&iommu->iommu, dev, NULL, dev_name(dev)); + if (err) + goto err_runtime_disable; + + err =3D iommu_device_register(&iommu->iommu, &vsi_iommu_ops, dev); + if (err) + goto err_remove_sysfs; + + return 0; + +err_remove_sysfs: + iommu_device_sysfs_remove(&iommu->iommu); +err_runtime_disable: + pm_runtime_disable(dev); +err_unprepare_clocks: + clk_bulk_unprepare(iommu->num_clocks, iommu->clocks); + return err; +} + +static void vsi_iommu_shutdown(struct platform_device *pdev) +{ + struct vsi_iommu *iommu =3D platform_get_drvdata(pdev); + + disable_irq(iommu->irq); + pm_runtime_force_suspend(&pdev->dev); +} + +static int __maybe_unused vsi_iommu_suspend(struct device *dev) +{ + struct vsi_iommu *iommu =3D dev_get_drvdata(dev); + + vsi_iommu_disable(iommu); + + clk_bulk_disable(iommu->num_clocks, iommu->clocks); + + return 0; +} + +static int __maybe_unused vsi_iommu_resume(struct device *dev) +{ + struct vsi_iommu *iommu =3D dev_get_drvdata(dev); + unsigned long flags; + int ret; + + ret =3D clk_bulk_enable(iommu->num_clocks, iommu->clocks); + if (ret) + return ret; + + if (iommu->domain) { + struct vsi_iommu_domain *vsi_domain =3D to_vsi_domain(iommu->domain); + + spin_lock_irqsave(&vsi_domain->lock, flags); + spin_lock(&iommu->lock); + vsi_iommu_enable(iommu, iommu->domain); + spin_unlock(&iommu->lock); + spin_unlock_irqrestore(&vsi_domain->lock, flags); + } + + return 0; +} + +static DEFINE_RUNTIME_DEV_PM_OPS(vsi_iommu_pm_ops, + vsi_iommu_suspend, vsi_iommu_resume, + NULL); + +static struct platform_driver rockchip_vsi_iommu_driver =3D { + .probe =3D vsi_iommu_probe, + .shutdown =3D vsi_iommu_shutdown, + .driver =3D { + .name =3D "vsi_iommu", + .of_match_table =3D vsi_iommu_dt_ids, + .pm =3D pm_sleep_ptr(&vsi_iommu_pm_ops), + .suppress_bind_attrs =3D true, + }, +}; +module_platform_driver(rockchip_vsi_iommu_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Benjamin Gaignard "); +MODULE_DESCRIPTION("Verisilicon IOMMU driver"); --=20 2.43.0 From nobody Tue Jun 16 01:18:29 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A2C273A3E92; Wed, 15 Apr 2026 07:23:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776237840; cv=none; b=h/t8pimqdJrEEfhUioCfy4E+AV/H5JP2j8nz0HlAPM56nxhlrRAj/LEP6Thvuh7s0UPRDRLtA6R01avemC4oHiP/OxAudzO+Ay9iTw3HRJLm++KbnuentiFJXAsuYfBX/swJXPC/wohSs1yGqPdRrz9GyBH3GvgPaPFwWBSze30= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776237840; c=relaxed/simple; bh=LlXq/U/YSTcXP/hcTIR6RtPx9lTAqG8OjX6Oh88UwRI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rgfxbZP9P7QNYCfv8IcbVALV+m9EQbUbjl2xrMq46KeYCz8btzXxO8KLi7XIIF0YkabbA8x5pJcsnWrLfAiNkljiPUaoiNYIUAFLqU7ZrkNa9WDjHECGVL8NGUwcnYscQ2VPjGnSLoX1xGhv/pMcbLtcMFu2WPMSMf0PV0O3Gxs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=dkZfUA+r; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="dkZfUA+r" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1776237837; bh=LlXq/U/YSTcXP/hcTIR6RtPx9lTAqG8OjX6Oh88UwRI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dkZfUA+rrV0vvJchW2Ug/pjKYtdUur1ExfZ6l8HTkPzrd1Mdds6FzURhN1kZw0hAw ERI5bmXCVq180PIJ0f1U38hxNADUC3knfP4ayjomqBQFoLqfQj4PFkeymvSDUaxD6C eJkFtCOTR7MKfnlYBOCA90kacP8smrcrEs6Iol2s2tJMYp9Fvav8bufHhr4H1OwMKj j01UJf4ht9zszoLpgohmaN3XLHaSIvoyUIb210vD02MXQZvKdjvDwk3yfo3q49MYUR /gTyxvC92AAz+8CZaoiv5PX80sD6ppJByT1HchdXOmKJEIvVOymlRjjfSBkwb2O0Km 6XP37ihSvJmVw== Received: from benjamin-XPS-13-9310.. (unknown [100.64.1.43]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: benjamin.gaignard) by bali.collaboradmins.com (Postfix) with ESMTPSA id DC9F417E1428; Wed, 15 Apr 2026 09:23:56 +0200 (CEST) From: Benjamin Gaignard To: joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, krzk+dt@kernel.org, conor+dt@kernel.org, heiko@sntech.de Cc: iommu@lists.linux.dev, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, kernel@collabora.com, Benjamin Gaignard Subject: [PATCH v14 4/5] arm64: dts: rockchip: Add verisilicon IOMMU node on RK3588 Date: Wed, 15 Apr 2026 09:23:40 +0200 Message-ID: <20260415072349.44237-5-benjamin.gaignard@collabora.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260415072349.44237-1-benjamin.gaignard@collabora.com> References: <20260415072349.44237-1-benjamin.gaignard@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add the device tree node for the Verisilicon IOMMU present in the RK3588 SoC. This IOMMU handles address translation for the VPU hardware blocks. Signed-off-by: Benjamin Gaignard --- arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boo= t/dts/rockchip/rk3588-base.dtsi index 7fe9593d8c19..7fde18feeaf8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi @@ -1428,6 +1428,17 @@ av1d: video-codec@fdc70000 { clock-names =3D "aclk", "hclk"; power-domains =3D <&power RK3588_PD_AV1>; resets =3D <&cru SRST_A_AV1>, <&cru SRST_P_AV1>, <&cru SRST_A_AV1_BIU>, = <&cru SRST_P_AV1_BIU>; + iommus =3D <&av1d_mmu>; + }; + + av1d_mmu: iommu@fdca0000 { + compatible =3D "rockchip,rk3588-av1-iommu", "verisilicon,iommu-1.2"; + reg =3D <0x0 0xfdca0000 0x0 0x600>; + interrupts =3D ; + clocks =3D <&cru ACLK_AV1>, <&cru PCLK_AV1>; + clock-names =3D "core", "iface"; + #iommu-cells =3D <0>; + power-domains =3D <&power RK3588_PD_AV1>; }; =20 vop: vop@fdd90000 { --=20 2.43.0 From nobody Tue Jun 16 01:18:29 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C05773AE6EE; Wed, 15 Apr 2026 07:23:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776237841; cv=none; b=F/SIOQwABKexYoiHLnkxWCk0aGM26xjX/ETNg36a469+FmNSY3ltlEOWzFhZGGnE0emnO9ee07I8i0rtgpjvMpi8bEFogMEQaJe4BAZapUHgqepIPJTH2/G4NferXK52M487qERyrbSAIccQurLnRWtf4Shx3d3FPFipRCpSEZU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776237841; c=relaxed/simple; bh=xq0NdgL1l0loSI+nYSoGevbj/g7OgzAQZIHb15BgSgw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u9b9awb2Z1TkaBOMiS4GvkMegdo6iJzWQHu9ji7kGQ3RJIpciT2bzHTQP1O+CXOZZhRj6fXSkjOgdWKwfLinQDd/JNC8Ru/6uUbfK9ljRvbZEWixYCc6u43I4V+W8uasn0aX1kMZMT+iYXGVCqRMu9nSnKqJqBv4ozz7i2IOaI0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=kxwvc+cI; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="kxwvc+cI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1776237837; bh=xq0NdgL1l0loSI+nYSoGevbj/g7OgzAQZIHb15BgSgw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kxwvc+cIAiSunnmoPcL8rhk101yoZ2cnPxwWQqYtanKdl6pfGjrgBV7Hm+0WuHlK/ TmG7pckOBUtrXLTrYtwNnbUgBdE9bSIFxoFPqo8yXOyy1ahFApLpEKYDWlEScrj4Mw +9vxA2OmPvPfnFPiXvwbsJu3iEIAUjrmLhJruKmANGjYztd3kVL+LiS+5dKhtHttbV OFoDpCW6OdkS4gA1wE1WmCUhI1j9wcPiKpXbsc8lk89k4Tn55npJ8niaHEiaNJnf1n vhAxqiVHDjyHCRup9jKsFYJNdYQupFiM+JwtuXcww1jNcsJ0ipWZ1OlTQ3N9rNRSle UJBycQWFA38yQ== Received: from benjamin-XPS-13-9310.. (unknown [100.64.1.43]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: benjamin.gaignard) by bali.collaboradmins.com (Postfix) with ESMTPSA id 62A0717E144F; Wed, 15 Apr 2026 09:23:57 +0200 (CEST) From: Benjamin Gaignard To: joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, krzk+dt@kernel.org, conor+dt@kernel.org, heiko@sntech.de Cc: iommu@lists.linux.dev, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, kernel@collabora.com, Benjamin Gaignard , Krzysztof Kozlowski Subject: [PATCH v14 5/5] arm64: defconfig: enable Verisilicon IOMMU for Rockchip RK3588 Date: Wed, 15 Apr 2026 09:23:41 +0200 Message-ID: <20260415072349.44237-6-benjamin.gaignard@collabora.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260415072349.44237-1-benjamin.gaignard@collabora.com> References: <20260415072349.44237-1-benjamin.gaignard@collabora.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Enable Verisilicon IOMMU used by Rockchip RK3588 AV1 hardware codec. This hardware block could be found in Radxa ROCK 5B board. Signed-off-by: Benjamin Gaignard Reviewed-by: Krzysztof Kozlowski --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index b67d5b1fc45b..b97f5008f6be 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1592,6 +1592,7 @@ CONFIG_ARM_SMMU_V3=3Dy CONFIG_MTK_IOMMU=3Dy CONFIG_QCOM_IOMMU=3Dy CONFIG_APPLE_DART=3Dm +CONFIG_VSI_IOMMU=3Dm CONFIG_REMOTEPROC=3Dy CONFIG_IMX_REMOTEPROC=3Dy CONFIG_MTK_SCP=3Dm --=20 2.43.0