145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/*
245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * IOMMU API for ARM architected SMMU implementations.
345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon *
445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * This program is free software; you can redistribute it and/or modify
545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * it under the terms of the GNU General Public License version 2 as
645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * published by the Free Software Foundation.
745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon *
845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * This program is distributed in the hope that it will be useful,
945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * but WITHOUT ANY WARRANTY; without even the implied warranty of
1045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * GNU General Public License for more details.
1245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon *
1345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * You should have received a copy of the GNU General Public License
1445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * along with this program; if not, write to the Free Software
1545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon *
1745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * Copyright (C) 2013 ARM Limited
1845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon *
1945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * Author: Will Deacon <will.deacon@arm.com>
2045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon *
2145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon * This driver currently supports:
2245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon *	- SMMUv1 and v2 implementations
2345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon *	- Stream-matching and stream-indexing
2445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon *	- v7/v8 long-descriptor format
2545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon *	- Non-secure access to the SMMU
2645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon *	- 4k and 64k pages, with contiguous pte hints.
2728d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon *	- Up to 48-bit addressing (dependent on VA_BITS)
2845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon *	- Context fault reporting
2945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon */
3045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
3145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define pr_fmt(fmt) "arm-smmu: " fmt
3245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
3345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/delay.h>
3445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/dma-mapping.h>
3545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/err.h>
3645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/interrupt.h>
3745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/io.h>
3845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/iommu.h>
3945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/mm.h>
4045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/module.h>
4145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/of.h>
42a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon#include <linux/pci.h>
4345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/platform_device.h>
4445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/slab.h>
4545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/spinlock.h>
4645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
4745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <linux/amba/bus.h>
4845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
4945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#include <asm/pgalloc.h>
5045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
5145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Maximum number of stream IDs assigned to a single device */
52636e97b0fb0a063dc89773b13064647f5da632cbAndreas Herrmann#define MAX_MASTER_STREAMIDS		MAX_PHANDLE_ARGS
5345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
5445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Maximum number of context banks per SMMU */
5545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_MAX_CBS		128
5645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
5745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Maximum number of mapping groups per SMMU */
5845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_MAX_SMRS		128
5945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
6045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* SMMU global address space */
6145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0(smmu)		((smmu)->base)
62c757e8528a304214d0a9be2e99011b94bf374d37Will Deacon#define ARM_SMMU_GR1(smmu)		((smmu)->base + (1 << (smmu)->pgshift))
6345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
643a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann/*
653a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann * SMMU global address space with conditional offset to access secure
663a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann * aliases of non-secure registers (e.g. nsCR0: 0x400, nsGFSR: 0x448,
673a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann * nsGFSYNR0: 0x450)
683a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann */
693a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann#define ARM_SMMU_GR0_NS(smmu)						\
703a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	((smmu)->base +							\
713a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann		((smmu->options & ARM_SMMU_OPT_SECURE_CFG_ACCESS)	\
723a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann			? 0x400 : 0))
733a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann
7445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Page table bits */
75cf2d45b19ddb361241f36d8c9f3d0b234a18459bWill Deacon#define ARM_SMMU_PTE_XN			(((pteval_t)3) << 53)
7645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_CONT		(((pteval_t)1) << 52)
7745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_AF			(((pteval_t)1) << 10)
7845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_SH_NS		(((pteval_t)0) << 8)
7945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_SH_OS		(((pteval_t)2) << 8)
8045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_SH_IS		(((pteval_t)3) << 8)
81cf2d45b19ddb361241f36d8c9f3d0b234a18459bWill Deacon#define ARM_SMMU_PTE_PAGE		(((pteval_t)3) << 0)
8245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
8345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#if PAGE_SIZE == SZ_4K
8445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_CONT_ENTRIES	16
8545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#elif PAGE_SIZE == SZ_64K
8645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_CONT_ENTRIES	32
8745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#else
8845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_CONT_ENTRIES	1
8945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#endif
9045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
9145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_CONT_SIZE		(PAGE_SIZE * ARM_SMMU_PTE_CONT_ENTRIES)
9245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_CONT_MASK		(~(ARM_SMMU_PTE_CONT_SIZE - 1))
9345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
9445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Stage-1 PTE */
9545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_AP_UNPRIV		(((pteval_t)1) << 6)
9645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_AP_RDONLY		(((pteval_t)2) << 6)
9745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_ATTRINDX_SHIFT	2
981463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon#define ARM_SMMU_PTE_nG			(((pteval_t)1) << 11)
9945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
10045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Stage-2 PTE */
10145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_HAP_FAULT		(((pteval_t)0) << 6)
10245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_HAP_READ		(((pteval_t)1) << 6)
10345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_HAP_WRITE		(((pteval_t)2) << 6)
10445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_MEMATTR_OIWB	(((pteval_t)0xf) << 2)
10545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_MEMATTR_NC		(((pteval_t)0x5) << 2)
10645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_PTE_MEMATTR_DEV	(((pteval_t)0x1) << 2)
10745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
10845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Configuration registers */
10945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_sCR0		0x0
11045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define sCR0_CLIENTPD			(1 << 0)
11145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define sCR0_GFRE			(1 << 1)
11245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define sCR0_GFIE			(1 << 2)
11345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define sCR0_GCFGFRE			(1 << 4)
11445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define sCR0_GCFGFIE			(1 << 5)
11545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define sCR0_USFCFG			(1 << 10)
11645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define sCR0_VMIDPNE			(1 << 11)
11745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define sCR0_PTM			(1 << 12)
11845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define sCR0_FB				(1 << 13)
11945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define sCR0_BSU_SHIFT			14
12045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define sCR0_BSU_MASK			0x3
12145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
12245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Identification registers */
12345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_ID0		0x20
12445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_ID1		0x24
12545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_ID2		0x28
12645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_ID3		0x2c
12745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_ID4		0x30
12845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_ID5		0x34
12945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_ID6		0x38
13045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_ID7		0x3c
13145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_sGFSR		0x48
13245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_sGFSYNR0		0x50
13345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_sGFSYNR1		0x54
13445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_sGFSYNR2		0x58
13545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_PIDR0		0xfe0
13645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_PIDR1		0xfe4
13745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_PIDR2		0xfe8
13845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
13945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID0_S1TS			(1 << 30)
14045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID0_S2TS			(1 << 29)
14145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID0_NTS				(1 << 28)
14245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID0_SMS				(1 << 27)
14345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID0_PTFS_SHIFT			24
14445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID0_PTFS_MASK			0x2
14545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID0_PTFS_V8_ONLY		0x2
14645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID0_CTTW			(1 << 14)
14745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID0_NUMIRPT_SHIFT		16
14845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID0_NUMIRPT_MASK		0xff
1493c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan#define ID0_NUMSIDB_SHIFT		9
1503c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan#define ID0_NUMSIDB_MASK		0xf
15145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID0_NUMSMRG_SHIFT		0
15245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID0_NUMSMRG_MASK		0xff
15345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
15445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID1_PAGESIZE			(1 << 31)
15545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID1_NUMPAGENDXB_SHIFT		28
15645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID1_NUMPAGENDXB_MASK		7
15745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID1_NUMS2CB_SHIFT		16
15845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID1_NUMS2CB_MASK		0xff
15945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID1_NUMCB_SHIFT			0
16045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID1_NUMCB_MASK			0xff
16145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
16245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID2_OAS_SHIFT			4
16345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID2_OAS_MASK			0xf
16445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID2_IAS_SHIFT			0
16545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID2_IAS_MASK			0xf
16645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID2_UBS_SHIFT			8
16745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID2_UBS_MASK			0xf
16845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID2_PTFS_4K			(1 << 12)
16945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID2_PTFS_16K			(1 << 13)
17045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ID2_PTFS_64K			(1 << 14)
17145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
17245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define PIDR2_ARCH_SHIFT		4
17345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define PIDR2_ARCH_MASK			0xf
17445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
17545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Global TLB invalidation */
17645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_STLBIALL		0x60
17745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_TLBIVMID		0x64
17845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_TLBIALLNSNH	0x68
17945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_TLBIALLH		0x6c
18045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_sTLBGSYNC		0x70
18145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_sTLBGSTATUS	0x74
18245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define sTLBGSTATUS_GSACTIVE		(1 << 0)
18345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TLB_LOOP_TIMEOUT		1000000	/* 1s! */
18445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
18545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Stream mapping registers */
18645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_SMR(n)		(0x800 + ((n) << 2))
18745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SMR_VALID			(1 << 31)
18845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SMR_MASK_SHIFT			16
18945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SMR_MASK_MASK			0x7fff
19045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SMR_ID_SHIFT			0
19145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SMR_ID_MASK			0x7fff
19245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
19345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR0_S2CR(n)		(0xc00 + ((n) << 2))
19445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define S2CR_CBNDX_SHIFT		0
19545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define S2CR_CBNDX_MASK			0xff
19645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define S2CR_TYPE_SHIFT			16
19745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define S2CR_TYPE_MASK			0x3
19845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define S2CR_TYPE_TRANS			(0 << S2CR_TYPE_SHIFT)
19945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define S2CR_TYPE_BYPASS		(1 << S2CR_TYPE_SHIFT)
20045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define S2CR_TYPE_FAULT			(2 << S2CR_TYPE_SHIFT)
20145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
20245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Context bank attribute registers */
20345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR1_CBAR(n)		(0x0 + ((n) << 2))
20445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_VMID_SHIFT			0
20545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_VMID_MASK			0xff
20657ca90f6800987ac274d7ba065ae6692cdf9bcd7Will Deacon#define CBAR_S1_BPSHCFG_SHIFT		8
20757ca90f6800987ac274d7ba065ae6692cdf9bcd7Will Deacon#define CBAR_S1_BPSHCFG_MASK		3
20857ca90f6800987ac274d7ba065ae6692cdf9bcd7Will Deacon#define CBAR_S1_BPSHCFG_NSH		3
20945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_S1_MEMATTR_SHIFT		12
21045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_S1_MEMATTR_MASK		0xf
21145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_S1_MEMATTR_WB		0xf
21245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_TYPE_SHIFT			16
21345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_TYPE_MASK			0x3
21445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_TYPE_S2_TRANS		(0 << CBAR_TYPE_SHIFT)
21545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_TYPE_S1_TRANS_S2_BYPASS	(1 << CBAR_TYPE_SHIFT)
21645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_TYPE_S1_TRANS_S2_FAULT	(2 << CBAR_TYPE_SHIFT)
21745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_TYPE_S1_TRANS_S2_TRANS	(3 << CBAR_TYPE_SHIFT)
21845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_IRPTNDX_SHIFT		24
21945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBAR_IRPTNDX_MASK		0xff
22045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
22145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_GR1_CBA2R(n)		(0x800 + ((n) << 2))
22245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBA2R_RW64_32BIT		(0 << 0)
22345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define CBA2R_RW64_64BIT		(1 << 0)
22445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
22545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Translation context bank */
22645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_CB_BASE(smmu)		((smmu)->base + ((smmu)->size >> 1))
227c757e8528a304214d0a9be2e99011b94bf374d37Will Deacon#define ARM_SMMU_CB(smmu, n)		((n) * (1 << (smmu)->pgshift))
22845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
22945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_CB_SCTLR		0x0
23045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_CB_RESUME		0x8
23145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_CB_TTBCR2		0x10
23245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_CB_TTBR0_LO		0x20
23345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_CB_TTBR0_HI		0x24
23445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_CB_TTBCR		0x30
23545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_CB_S1_MAIR0		0x38
23645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_CB_FSR			0x58
23745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_CB_FAR_LO		0x60
23845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_CB_FAR_HI		0x64
23945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_CB_FSYNR0		0x68
2401463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon#define ARM_SMMU_CB_S1_TLBIASID		0x610
24145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
24245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SCTLR_S1_ASIDPNE		(1 << 12)
24345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SCTLR_CFCFG			(1 << 7)
24445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SCTLR_CFIE			(1 << 6)
24545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SCTLR_CFRE			(1 << 5)
24645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SCTLR_E				(1 << 4)
24745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SCTLR_AFE			(1 << 2)
24845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SCTLR_TRE			(1 << 1)
24945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SCTLR_M				(1 << 0)
25045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define SCTLR_EAE_SBOP			(SCTLR_AFE | SCTLR_TRE)
25145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
25245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define RESUME_RETRY			(0 << 0)
25345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define RESUME_TERMINATE		(1 << 0)
25445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
25545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_EAE			(1 << 31)
25645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
25745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_PASIZE_SHIFT		16
25845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_PASIZE_MASK		0x7
25945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
26045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_TG0_4K			(0 << 14)
26145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_TG0_64K			(1 << 14)
26245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
26345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_SH0_SHIFT			12
26445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_SH0_MASK			0x3
26545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_SH_NS			0
26645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_SH_OS			2
26745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_SH_IS			3
26845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
26945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_ORGN0_SHIFT		10
27045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_IRGN0_SHIFT		8
27145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_RGN_MASK			0x3
27245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_RGN_NC			0
27345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_RGN_WBWA			1
27445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_RGN_WT			2
27545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_RGN_WB			3
27645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
27745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_SL0_SHIFT			6
27845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_SL0_MASK			0x3
27945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_SL0_LVL_2			0
28045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_SL0_LVL_1			1
28145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
28245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_T1SZ_SHIFT		16
28345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_T0SZ_SHIFT		0
28445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR_SZ_MASK			0xf
28545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
28645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR2_SEP_SHIFT		15
28745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR2_SEP_MASK			0x7
28845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
28945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR2_PASIZE_SHIFT		0
29045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR2_PASIZE_MASK		0x7
29145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
29245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Common definitions for PASize and SEP fields */
29345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR2_ADDR_32			0
29445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR2_ADDR_36			1
29545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR2_ADDR_40			2
29645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR2_ADDR_42			3
29745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR2_ADDR_44			4
29845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define TTBCR2_ADDR_48			5
29945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
3001463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon#define TTBRn_HI_ASID_SHIFT		16
3011463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon
30245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define MAIR_ATTR_SHIFT(n)		((n) << 3)
30345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define MAIR_ATTR_MASK			0xff
30445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define MAIR_ATTR_DEVICE		0x04
30545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define MAIR_ATTR_NC			0x44
30645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define MAIR_ATTR_WBRWA			0xff
30745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define MAIR_ATTR_IDX_NC		0
30845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define MAIR_ATTR_IDX_CACHE		1
30945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define MAIR_ATTR_IDX_DEV		2
31045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
31145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define FSR_MULTI			(1 << 31)
31245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define FSR_SS				(1 << 30)
31345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define FSR_UUT				(1 << 8)
31445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define FSR_ASF				(1 << 7)
31545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define FSR_TLBLKF			(1 << 6)
31645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define FSR_TLBMCF			(1 << 5)
31745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define FSR_EF				(1 << 4)
31845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define FSR_PF				(1 << 3)
31945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define FSR_AFF				(1 << 2)
32045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define FSR_TF				(1 << 1)
32145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
3222907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys#define FSR_IGN				(FSR_AFF | FSR_ASF | \
3232907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys					 FSR_TLBMCF | FSR_TLBLKF)
3242907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys#define FSR_FAULT			(FSR_MULTI | FSR_SS | FSR_UUT | \
325adaba320916d246af56821a1aab81a715091e7e5Will Deacon					 FSR_EF | FSR_PF | FSR_TF | FSR_IGN)
32645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
32745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define FSYNR0_WNR			(1 << 4)
32845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
3294cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will Deaconstatic int force_stage;
3304cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will Deaconmodule_param_named(force_stage, force_stage, int, S_IRUGO | S_IWUSR);
3314cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will DeaconMODULE_PARM_DESC(force_stage,
3324cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will Deacon	"Force SMMU mappings to be installed at a particular stage of translation. A value of '1' or '2' forces the corresponding stage. All other values are ignored (i.e. no stage is forced). Note that selecting a specific stage will disable support for nested translation.");
3334cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will Deacon
334093604033361928f7f355b4d1766d0179ae747fbRobin Murphyenum arm_smmu_arch_version {
335093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	ARM_SMMU_V1 = 1,
336093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	ARM_SMMU_V2,
337093604033361928f7f355b4d1766d0179ae747fbRobin Murphy};
338093604033361928f7f355b4d1766d0179ae747fbRobin Murphy
33945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstruct arm_smmu_smr {
34045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u8				idx;
34145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u16				mask;
34245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u16				id;
34345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon};
34445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
345a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deaconstruct arm_smmu_master_cfg {
34645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int				num_streamids;
34745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u16				streamids[MAX_MASTER_STREAMIDS];
34845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_smr		*smrs;
34945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon};
35045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
351a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deaconstruct arm_smmu_master {
352a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	struct device_node		*of_node;
353a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	struct rb_node			node;
354a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	struct arm_smmu_master_cfg	cfg;
355a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon};
356a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon
35745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstruct arm_smmu_device {
35845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct device			*dev;
35945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
36045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	void __iomem			*base;
36145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	unsigned long			size;
362c757e8528a304214d0a9be2e99011b94bf374d37Will Deacon	unsigned long			pgshift;
36345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
36445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_FEAT_COHERENT_WALK	(1 << 0)
36545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_FEAT_STREAM_MATCH	(1 << 1)
36645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_FEAT_TRANS_S1		(1 << 2)
36745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_FEAT_TRANS_S2		(1 << 3)
36845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#define ARM_SMMU_FEAT_TRANS_NESTED	(1 << 4)
36945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u32				features;
3703a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann
3713a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann#define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
3723a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	u32				options;
373093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	enum arm_smmu_arch_version	version;
37445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
37545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u32				num_context_banks;
37645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u32				num_s2_context_banks;
37745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	DECLARE_BITMAP(context_map, ARM_SMMU_MAX_CBS);
37845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	atomic_t			irptndx;
37945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
38045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u32				num_mapping_groups;
38145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	DECLARE_BITMAP(smr_map, ARM_SMMU_MAX_SMRS);
38245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
38328d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon	unsigned long			s1_input_size;
38445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	unsigned long			s1_output_size;
38528d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon	unsigned long			s2_input_size;
38645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	unsigned long			s2_output_size;
38745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
38845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u32				num_global_irqs;
38945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u32				num_context_irqs;
39045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	unsigned int			*irqs;
39145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
39245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct list_head		list;
39345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct rb_root			masters;
39445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon};
39545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
39645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstruct arm_smmu_cfg {
39745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u8				cbndx;
39845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u8				irptndx;
39945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u32				cbar;
40045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pgd_t				*pgd;
40145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon};
402faea13b72dbdb77e4d6ad83344596486611708b0Dan Carpenter#define INVALID_IRPTNDX			0xff
40345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
404ecfadb6e5b49a0a56df2038bf39f1fcd652788b9Will Deacon#define ARM_SMMU_CB_ASID(cfg)		((cfg)->cbndx)
405ecfadb6e5b49a0a56df2038bf39f1fcd652788b9Will Deacon#define ARM_SMMU_CB_VMID(cfg)		((cfg)->cbndx + 1)
406ecfadb6e5b49a0a56df2038bf39f1fcd652788b9Will Deacon
40745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstruct arm_smmu_domain {
40844680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_device		*smmu;
40944680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_cfg		cfg;
410c9d09e2748eaa55cac2af274574baa6368189bc1Will Deacon	spinlock_t			lock;
41145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon};
41245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
41345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic DEFINE_SPINLOCK(arm_smmu_devices_lock);
41445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic LIST_HEAD(arm_smmu_devices);
41545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
4163a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmannstruct arm_smmu_option_prop {
4173a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	u32 opt;
4183a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	const char *prop;
4193a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann};
4203a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann
4212907320df3189420cb66178a86b2917f4b64018fMitchel Humpherysstatic struct arm_smmu_option_prop arm_smmu_options[] = {
4223a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	{ ARM_SMMU_OPT_SECURE_CFG_ACCESS, "calxeda,smmu-secure-config-access" },
4233a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	{ 0, NULL},
4243a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann};
4253a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann
4263a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmannstatic void parse_driver_options(struct arm_smmu_device *smmu)
4273a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann{
4283a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	int i = 0;
4292907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys
4303a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	do {
4313a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann		if (of_property_read_bool(smmu->dev->of_node,
4323a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann						arm_smmu_options[i].prop)) {
4333a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann			smmu->options |= arm_smmu_options[i].opt;
4343a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann			dev_notice(smmu->dev, "option %s\n",
4353a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann				arm_smmu_options[i].prop);
4363a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann		}
4373a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	} while (arm_smmu_options[++i].opt);
4383a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann}
4393a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann
4408f68f8e28298abdf518648e794c71e534eb8841cWill Deaconstatic struct device_node *dev_get_dev_node(struct device *dev)
441a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon{
442a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	if (dev_is_pci(dev)) {
443a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		struct pci_bus *bus = to_pci_dev(dev)->bus;
4442907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys
445a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		while (!pci_is_root_bus(bus))
446a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon			bus = bus->parent;
4478f68f8e28298abdf518648e794c71e534eb8841cWill Deacon		return bus->bridge->parent->of_node;
448a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	}
449a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon
4508f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	return dev->of_node;
451a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon}
452a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon
45345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu,
45445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon						struct device_node *dev_node)
45545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
45645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct rb_node *node = smmu->masters.rb_node;
45745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
45845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	while (node) {
45945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		struct arm_smmu_master *master;
4602907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys
46145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		master = container_of(node, struct arm_smmu_master, node);
46245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
46345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (dev_node < master->of_node)
46445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			node = node->rb_left;
46545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		else if (dev_node > master->of_node)
46645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			node = node->rb_right;
46745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		else
46845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			return master;
46945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
47045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
47145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return NULL;
47245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
47345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
474a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deaconstatic struct arm_smmu_master_cfg *
4758f68f8e28298abdf518648e794c71e534eb8841cWill Deaconfind_smmu_master_cfg(struct device *dev)
476a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon{
4778f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	struct arm_smmu_master_cfg *cfg = NULL;
4788f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	struct iommu_group *group = iommu_group_get(dev);
479a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon
4808f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	if (group) {
4818f68f8e28298abdf518648e794c71e534eb8841cWill Deacon		cfg = iommu_group_get_iommudata(group);
4828f68f8e28298abdf518648e794c71e534eb8841cWill Deacon		iommu_group_put(group);
4838f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	}
484a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon
4858f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	return cfg;
486a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon}
487a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon
48845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int insert_smmu_master(struct arm_smmu_device *smmu,
48945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			      struct arm_smmu_master *master)
49045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
49145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct rb_node **new, *parent;
49245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
49345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	new = &smmu->masters.rb_node;
49445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	parent = NULL;
49545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	while (*new) {
4962907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys		struct arm_smmu_master *this
4972907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys			= container_of(*new, struct arm_smmu_master, node);
49845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
49945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		parent = *new;
50045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (master->of_node < this->of_node)
50145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			new = &((*new)->rb_left);
50245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		else if (master->of_node > this->of_node)
50345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			new = &((*new)->rb_right);
50445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		else
50545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			return -EEXIST;
50645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
50745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
50845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	rb_link_node(&master->node, parent, new);
50945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	rb_insert_color(&master->node, &smmu->masters);
51045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return 0;
51145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
51245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
51345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int register_smmu_master(struct arm_smmu_device *smmu,
51445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				struct device *dev,
51545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				struct of_phandle_args *masterspec)
51645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
51745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int i;
51845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_master *master;
51945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
52045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	master = find_smmu_master(smmu, masterspec->np);
52145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (master) {
52245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(dev,
52345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			"rejecting multiple registrations for master device %s\n",
52445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			masterspec->np->name);
52545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -EBUSY;
52645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
52745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
52845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (masterspec->args_count > MAX_MASTER_STREAMIDS) {
52945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(dev,
53045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			"reached maximum number (%d) of stream IDs for master device %s\n",
53145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			MAX_MASTER_STREAMIDS, masterspec->np->name);
53245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENOSPC;
53345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
53445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
53545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	master = devm_kzalloc(dev, sizeof(*master), GFP_KERNEL);
53645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!master)
53745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENOMEM;
53845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
539a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	master->of_node			= masterspec->np;
540a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	master->cfg.num_streamids	= masterspec->args_count;
54145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
5423c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan	for (i = 0; i < master->cfg.num_streamids; ++i) {
5433c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan		u16 streamid = masterspec->args[i];
54445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
5453c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan		if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) &&
5463c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan		     (streamid >= smmu->num_mapping_groups)) {
5473c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan			dev_err(dev,
5483c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan				"stream ID for master device %s greater than maximum allowed (%d)\n",
5493c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan				masterspec->np->name, smmu->num_mapping_groups);
5503c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan			return -ERANGE;
5513c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan		}
5523c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan		master->cfg.streamids[i] = streamid;
5533c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan	}
55445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return insert_smmu_master(smmu, master);
55545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
55645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
55744680eedf9409daf0fed618ae101f35d1f83d1a4Will Deaconstatic struct arm_smmu_device *find_smmu_for_device(struct device *dev)
55845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
55944680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_device *smmu;
560a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	struct arm_smmu_master *master = NULL;
5618f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	struct device_node *dev_node = dev_get_dev_node(dev);
56245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
56345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	spin_lock(&arm_smmu_devices_lock);
56444680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	list_for_each_entry(smmu, &arm_smmu_devices, list) {
565a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		master = find_smmu_master(smmu, dev_node);
566a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		if (master)
567a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon			break;
568a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	}
56945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	spin_unlock(&arm_smmu_devices_lock);
57044680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon
571a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	return master ? smmu : NULL;
57245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
57345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
57445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int __arm_smmu_alloc_bitmap(unsigned long *map, int start, int end)
57545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
57645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int idx;
57745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
57845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	do {
57945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		idx = find_next_zero_bit(map, end, start);
58045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (idx == end)
58145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			return -ENOSPC;
58245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} while (test_and_set_bit(idx, map));
58345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
58445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return idx;
58545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
58645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
58745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void __arm_smmu_free_bitmap(unsigned long *map, int idx)
58845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
58945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	clear_bit(idx, map);
59045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
59145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
59245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon/* Wait for any pending TLB invalidations to complete */
59345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_tlb_sync(struct arm_smmu_device *smmu)
59445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
59545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int count = 0;
59645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
59745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
59845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	writel_relaxed(0, gr0_base + ARM_SMMU_GR0_sTLBGSYNC);
59945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	while (readl_relaxed(gr0_base + ARM_SMMU_GR0_sTLBGSTATUS)
60045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	       & sTLBGSTATUS_GSACTIVE) {
60145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		cpu_relax();
60245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (++count == TLB_LOOP_TIMEOUT) {
60345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			dev_err_ratelimited(smmu->dev,
60445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			"TLB sync timed out -- SMMU may be deadlocked\n");
60545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			return;
60645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
60745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		udelay(1);
60845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
60945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
61045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
61144680eedf9409daf0fed618ae101f35d1f83d1a4Will Deaconstatic void arm_smmu_tlb_inv_context(struct arm_smmu_domain *smmu_domain)
6121463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon{
61344680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
61444680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_device *smmu = smmu_domain->smmu;
6151463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	void __iomem *base = ARM_SMMU_GR0(smmu);
6161463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
6171463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon
6181463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	if (stage1) {
6191463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon		base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
620ecfadb6e5b49a0a56df2038bf39f1fcd652788b9Will Deacon		writel_relaxed(ARM_SMMU_CB_ASID(cfg),
621ecfadb6e5b49a0a56df2038bf39f1fcd652788b9Will Deacon			       base + ARM_SMMU_CB_S1_TLBIASID);
6221463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	} else {
6231463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon		base = ARM_SMMU_GR0(smmu);
624ecfadb6e5b49a0a56df2038bf39f1fcd652788b9Will Deacon		writel_relaxed(ARM_SMMU_CB_VMID(cfg),
625ecfadb6e5b49a0a56df2038bf39f1fcd652788b9Will Deacon			       base + ARM_SMMU_GR0_TLBIVMID);
6261463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	}
6271463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon
6281463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	arm_smmu_tlb_sync(smmu);
6291463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon}
6301463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon
63145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic irqreturn_t arm_smmu_context_fault(int irq, void *dev)
63245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
63345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int flags, ret;
63445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u32 fsr, far, fsynr, resume;
63545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	unsigned long iova;
63645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct iommu_domain *domain = dev;
63745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_domain *smmu_domain = domain->priv;
63844680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
63944680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_device *smmu = smmu_domain->smmu;
64045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	void __iomem *cb_base;
64145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
64244680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
64345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR);
64445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
64545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!(fsr & FSR_FAULT))
64645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return IRQ_NONE;
64745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
64845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (fsr & FSR_IGN)
64945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err_ratelimited(smmu->dev,
65070c9a7db93a152e975c4158b944c6b50579415c2Hans Wennborg				    "Unexpected context fault (fsr 0x%x)\n",
65145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				    fsr);
65245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
65345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0);
65445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	flags = fsynr & FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ;
65545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
65645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	far = readl_relaxed(cb_base + ARM_SMMU_CB_FAR_LO);
65745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	iova = far;
65845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#ifdef CONFIG_64BIT
65945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	far = readl_relaxed(cb_base + ARM_SMMU_CB_FAR_HI);
66045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	iova |= ((unsigned long)far << 32);
66145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#endif
66245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
66345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!report_iommu_fault(domain, smmu->dev, iova, flags)) {
66445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		ret = IRQ_HANDLED;
66545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		resume = RESUME_RETRY;
66645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} else {
6672ef0f03120ea2ad64d0e70f032a58e6c13603cdcAndreas Herrmann		dev_err_ratelimited(smmu->dev,
6682ef0f03120ea2ad64d0e70f032a58e6c13603cdcAndreas Herrmann		    "Unhandled context fault: iova=0x%08lx, fsynr=0x%x, cb=%d\n",
66944680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		    iova, fsynr, cfg->cbndx);
67045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		ret = IRQ_NONE;
67145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		resume = RESUME_TERMINATE;
67245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
67345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
67445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Clear the faulting FSR */
67545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	writel(fsr, cb_base + ARM_SMMU_CB_FSR);
67645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
67745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Retry or terminate any stalled transactions */
67845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (fsr & FSR_SS)
67945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		writel_relaxed(resume, cb_base + ARM_SMMU_CB_RESUME);
68045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
68145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return ret;
68245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
68345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
68445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic irqreturn_t arm_smmu_global_fault(int irq, void *dev)
68545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
68645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u32 gfsr, gfsynr0, gfsynr1, gfsynr2;
68745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_device *smmu = dev;
6883a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	void __iomem *gr0_base = ARM_SMMU_GR0_NS(smmu);
68945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
69045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	gfsr = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSR);
69145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	gfsynr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR0);
69245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	gfsynr1 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR1);
69345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	gfsynr2 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR2);
69445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
6953a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	if (!gfsr)
6963a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann		return IRQ_NONE;
6973a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann
69845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	dev_err_ratelimited(smmu->dev,
69945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		"Unexpected global fault, this could be serious\n");
70045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	dev_err_ratelimited(smmu->dev,
70145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		"\tGFSR 0x%08x, GFSYNR0 0x%08x, GFSYNR1 0x%08x, GFSYNR2 0x%08x\n",
70245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		gfsr, gfsynr0, gfsynr1, gfsynr2);
70345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
70445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	writel(gfsr, gr0_base + ARM_SMMU_GR0_sGFSR);
705adaba320916d246af56821a1aab81a715091e7e5Will Deacon	return IRQ_HANDLED;
70645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
70745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
7086dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deaconstatic void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr,
7096dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon				   size_t size)
7106dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon{
7116dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon	unsigned long offset = (unsigned long)addr & ~PAGE_MASK;
7126dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon
7136dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon
7146dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon	/* Ensure new page tables are visible to the hardware walker */
7156dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon	if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) {
7163aa80ea4c90d46ffbe200d05b9ceb997001b36dfWill Deacon		dsb(ishst);
7176dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon	} else {
7186dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon		/*
7196dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon		 * If the SMMU can't walk tables in the CPU caches, treat them
7206dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon		 * like non-coherent DMA since we need to flush the new entries
7216dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon		 * all the way out to memory. There's no possibility of
7226dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon		 * recursion here as the SMMU table walker will not be wired
7236dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon		 * through another SMMU.
7246dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon		 */
7256dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon		dma_map_page(smmu->dev, virt_to_page(addr), offset, size,
7266dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon				DMA_TO_DEVICE);
7276dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon	}
7286dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon}
7296dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon
73045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
73145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
73245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u32 reg;
73345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	bool stage1;
73444680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
73544680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_device *smmu = smmu_domain->smmu;
73645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	void __iomem *cb_base, *gr0_base, *gr1_base;
73745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
73845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	gr0_base = ARM_SMMU_GR0(smmu);
73945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	gr1_base = ARM_SMMU_GR1(smmu);
74044680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
74144680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
74245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
74345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* CBAR */
74444680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	reg = cfg->cbar;
745093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	if (smmu->version == ARM_SMMU_V1)
7462907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys		reg |= cfg->irptndx << CBAR_IRPTNDX_SHIFT;
74745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
74857ca90f6800987ac274d7ba065ae6692cdf9bcd7Will Deacon	/*
74957ca90f6800987ac274d7ba065ae6692cdf9bcd7Will Deacon	 * Use the weakest shareability/memory types, so they are
75057ca90f6800987ac274d7ba065ae6692cdf9bcd7Will Deacon	 * overridden by the ttbcr/pte.
75157ca90f6800987ac274d7ba065ae6692cdf9bcd7Will Deacon	 */
75257ca90f6800987ac274d7ba065ae6692cdf9bcd7Will Deacon	if (stage1) {
75357ca90f6800987ac274d7ba065ae6692cdf9bcd7Will Deacon		reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
75457ca90f6800987ac274d7ba065ae6692cdf9bcd7Will Deacon			(CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
75557ca90f6800987ac274d7ba065ae6692cdf9bcd7Will Deacon	} else {
75644680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		reg |= ARM_SMMU_CB_VMID(cfg) << CBAR_VMID_SHIFT;
75757ca90f6800987ac274d7ba065ae6692cdf9bcd7Will Deacon	}
75844680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx));
75945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
760093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	if (smmu->version > ARM_SMMU_V1) {
76145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		/* CBA2R */
76245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#ifdef CONFIG_64BIT
76345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		reg = CBA2R_RW64_64BIT;
76445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#else
76545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		reg = CBA2R_RW64_32BIT;
76645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#endif
76745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		writel_relaxed(reg,
76844680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon			       gr1_base + ARM_SMMU_GR1_CBA2R(cfg->cbndx));
76945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
77045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		/* TTBCR2 */
77128d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon		switch (smmu->s1_input_size) {
77245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		case 32:
77345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg = (TTBCR2_ADDR_32 << TTBCR2_SEP_SHIFT);
77445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
77545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		case 36:
77645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg = (TTBCR2_ADDR_36 << TTBCR2_SEP_SHIFT);
77745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
77845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		case 39:
7794d09d99d543ec28b2280a1f62382697f47ea6366Will Deacon		case 40:
78045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg = (TTBCR2_ADDR_40 << TTBCR2_SEP_SHIFT);
78145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
78245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		case 42:
78345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg = (TTBCR2_ADDR_42 << TTBCR2_SEP_SHIFT);
78445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
78545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		case 44:
78645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg = (TTBCR2_ADDR_44 << TTBCR2_SEP_SHIFT);
78745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
78845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		case 48:
78945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg = (TTBCR2_ADDR_48 << TTBCR2_SEP_SHIFT);
79045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
79145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
79245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
79345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		switch (smmu->s1_output_size) {
79445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		case 32:
79545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg |= (TTBCR2_ADDR_32 << TTBCR2_PASIZE_SHIFT);
79645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
79745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		case 36:
79845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg |= (TTBCR2_ADDR_36 << TTBCR2_PASIZE_SHIFT);
79945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
80045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		case 39:
8014d09d99d543ec28b2280a1f62382697f47ea6366Will Deacon		case 40:
80245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg |= (TTBCR2_ADDR_40 << TTBCR2_PASIZE_SHIFT);
80345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
80445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		case 42:
80545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg |= (TTBCR2_ADDR_42 << TTBCR2_PASIZE_SHIFT);
80645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
80745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		case 44:
80845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg |= (TTBCR2_ADDR_44 << TTBCR2_PASIZE_SHIFT);
80945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
81045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		case 48:
81145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg |= (TTBCR2_ADDR_48 << TTBCR2_PASIZE_SHIFT);
81245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
81345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
81445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
81545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (stage1)
81645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR2);
81745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
81845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
81945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* TTBR0 */
82044680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	arm_smmu_flush_pgtable(smmu, cfg->pgd,
8216dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon			       PTRS_PER_PGD * sizeof(pgd_t));
82244680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	reg = __pa(cfg->pgd);
82345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO);
82444680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	reg = (phys_addr_t)__pa(cfg->pgd) >> 32;
8251463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	if (stage1)
82644680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		reg |= ARM_SMMU_CB_ASID(cfg) << TTBRn_HI_ASID_SHIFT;
82745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_HI);
82845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
82945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/*
83045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * TTBCR
83145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * We use long descriptor, with inner-shareable WBWA tables in TTBR0.
83245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 */
833093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	if (smmu->version > ARM_SMMU_V1) {
83445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (PAGE_SIZE == SZ_4K)
83545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg = TTBCR_TG0_4K;
83645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		else
83745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			reg = TTBCR_TG0_64K;
83845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
83945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (!stage1) {
84028d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon			reg |= (64 - smmu->s2_input_size) << TTBCR_T0SZ_SHIFT;
841a65217a4bcdb654e04fcc42b302d8a15708e14ceWill Deacon
84245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			switch (smmu->s2_output_size) {
84345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			case 32:
84445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				reg |= (TTBCR2_ADDR_32 << TTBCR_PASIZE_SHIFT);
84545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				break;
84645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			case 36:
84745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				reg |= (TTBCR2_ADDR_36 << TTBCR_PASIZE_SHIFT);
84845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				break;
84945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			case 40:
85045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				reg |= (TTBCR2_ADDR_40 << TTBCR_PASIZE_SHIFT);
85145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				break;
85245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			case 42:
85345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				reg |= (TTBCR2_ADDR_42 << TTBCR_PASIZE_SHIFT);
85445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				break;
85545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			case 44:
85645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				reg |= (TTBCR2_ADDR_44 << TTBCR_PASIZE_SHIFT);
85745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				break;
85845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			case 48:
85945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				reg |= (TTBCR2_ADDR_48 << TTBCR_PASIZE_SHIFT);
86045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				break;
86145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			}
86245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		} else {
86328d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon			reg |= (64 - smmu->s1_input_size) << TTBCR_T0SZ_SHIFT;
86445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
86545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} else {
86645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		reg = 0;
86745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
86845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
86945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	reg |= TTBCR_EAE |
87045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	      (TTBCR_SH_IS << TTBCR_SH0_SHIFT) |
87145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	      (TTBCR_RGN_WBWA << TTBCR_ORGN0_SHIFT) |
8721fc870c7efa364862c3bc792cfbdb38afea26742Olav Haugan	      (TTBCR_RGN_WBWA << TTBCR_IRGN0_SHIFT);
8731fc870c7efa364862c3bc792cfbdb38afea26742Olav Haugan
8741fc870c7efa364862c3bc792cfbdb38afea26742Olav Haugan	if (!stage1)
8751fc870c7efa364862c3bc792cfbdb38afea26742Olav Haugan		reg |= (TTBCR_SL0_LVL_1 << TTBCR_SL0_SHIFT);
8761fc870c7efa364862c3bc792cfbdb38afea26742Olav Haugan
87745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR);
87845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
87945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* MAIR0 (stage-1 only) */
88045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (stage1) {
88145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		reg = (MAIR_ATTR_NC << MAIR_ATTR_SHIFT(MAIR_ATTR_IDX_NC)) |
88245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		      (MAIR_ATTR_WBRWA << MAIR_ATTR_SHIFT(MAIR_ATTR_IDX_CACHE)) |
88345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		      (MAIR_ATTR_DEVICE << MAIR_ATTR_SHIFT(MAIR_ATTR_IDX_DEV));
88445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		writel_relaxed(reg, cb_base + ARM_SMMU_CB_S1_MAIR0);
88545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
88645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
88745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* SCTLR */
88845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	reg = SCTLR_CFCFG | SCTLR_CFIE | SCTLR_CFRE | SCTLR_M | SCTLR_EAE_SBOP;
88945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (stage1)
89045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		reg |= SCTLR_S1_ASIDPNE;
89145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#ifdef __BIG_ENDIAN
89245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	reg |= SCTLR_E;
89345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#endif
89425724841dfaed05f23a3ddaaaed5c9b61ceea7bdWill Deacon	writel_relaxed(reg, cb_base + ARM_SMMU_CB_SCTLR);
89545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
89645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
89745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_init_domain_context(struct iommu_domain *domain,
89844680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon					struct arm_smmu_device *smmu)
89945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
900a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	int irq, start, ret = 0;
901a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	unsigned long flags;
90245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_domain *smmu_domain = domain->priv;
90344680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
90445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
905a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	spin_lock_irqsave(&smmu_domain->lock, flags);
906a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	if (smmu_domain->smmu)
907a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys		goto out_unlock;
908a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys
90945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) {
91045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		/*
91145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		 * We will likely want to change this if/when KVM gets
91245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		 * involved.
91345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		 */
91444680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;
91545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		start = smmu->num_s2_context_banks;
9169c5c92e35cf5c4f7ee523d62a6bf9d5dc290350bWill Deacon	} else if (smmu->features & ARM_SMMU_FEAT_TRANS_S1) {
91744680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;
91845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		start = smmu->num_s2_context_banks;
9199c5c92e35cf5c4f7ee523d62a6bf9d5dc290350bWill Deacon	} else {
9209c5c92e35cf5c4f7ee523d62a6bf9d5dc290350bWill Deacon		cfg->cbar = CBAR_TYPE_S2_TRANS;
9219c5c92e35cf5c4f7ee523d62a6bf9d5dc290350bWill Deacon		start = 0;
92245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
92345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
92445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
92545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				      smmu->num_context_banks);
92645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (IS_ERR_VALUE(ret))
927a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys		goto out_unlock;
92845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
92944680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	cfg->cbndx = ret;
930093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	if (smmu->version == ARM_SMMU_V1) {
93144680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		cfg->irptndx = atomic_inc_return(&smmu->irptndx);
93244680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		cfg->irptndx %= smmu->num_context_irqs;
93345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} else {
93444680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		cfg->irptndx = cfg->cbndx;
93545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
93645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
937a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	ACCESS_ONCE(smmu_domain->smmu) = smmu;
938a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	arm_smmu_init_context_bank(smmu_domain);
939a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	spin_unlock_irqrestore(&smmu_domain->lock, flags);
940a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys
94144680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
94245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED,
94345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			  "arm-smmu-context-fault", domain);
94445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (IS_ERR_VALUE(ret)) {
94545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n",
94644680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon			cfg->irptndx, irq);
94744680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		cfg->irptndx = INVALID_IRPTNDX;
94845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
94945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
950a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	return 0;
95145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
952a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherysout_unlock:
953a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	spin_unlock_irqrestore(&smmu_domain->lock, flags);
95445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return ret;
95545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
95645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
95745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
95845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
95945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_domain *smmu_domain = domain->priv;
96044680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_device *smmu = smmu_domain->smmu;
96144680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
9621463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	void __iomem *cb_base;
96345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int irq;
96445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
96545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!smmu)
96645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return;
96745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
9681463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	/* Disable the context bank and nuke the TLB before freeing it. */
96944680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
9701463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);
97144680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	arm_smmu_tlb_inv_context(smmu_domain);
9721463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon
97344680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	if (cfg->irptndx != INVALID_IRPTNDX) {
97444680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
97545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		free_irq(irq, domain);
97645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
97745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
97844680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
97945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
98045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
98145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_domain_init(struct iommu_domain *domain)
98245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
98345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_domain *smmu_domain;
98445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pgd_t *pgd;
98545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
98645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/*
98745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * Allocate the domain and initialise some of its data structures.
98845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * We can't really do anything meaningful until we've added a
98945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * master.
99045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 */
99145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	smmu_domain = kzalloc(sizeof(*smmu_domain), GFP_KERNEL);
99245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!smmu_domain)
99345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENOMEM;
99445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
9952907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys	pgd = kcalloc(PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL);
99645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!pgd)
99745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		goto out_free_domain;
99844680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	smmu_domain->cfg.pgd = pgd;
99945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1000c9d09e2748eaa55cac2af274574baa6368189bc1Will Deacon	spin_lock_init(&smmu_domain->lock);
100145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	domain->priv = smmu_domain;
100245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return 0;
100345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
100445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconout_free_domain:
100545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	kfree(smmu_domain);
100645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return -ENOMEM;
100745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
100845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
100945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_free_ptes(pmd_t *pmd)
101045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
101145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pgtable_t table = pmd_pgtable(*pmd);
10122907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys
101345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	__free_page(table);
101445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
101545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
101645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_free_pmds(pud_t *pud)
101745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
101845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int i;
101945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pmd_t *pmd, *pmd_base = pmd_offset(pud, 0);
102045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
102145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pmd = pmd_base;
102245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	for (i = 0; i < PTRS_PER_PMD; ++i) {
102345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (pmd_none(*pmd))
102445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			continue;
102545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
102645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		arm_smmu_free_ptes(pmd);
102745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		pmd++;
102845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
102945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
103045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pmd_free(NULL, pmd_base);
103145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
103245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
103345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_free_puds(pgd_t *pgd)
103445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
103545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int i;
103645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pud_t *pud, *pud_base = pud_offset(pgd, 0);
103745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
103845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pud = pud_base;
103945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	for (i = 0; i < PTRS_PER_PUD; ++i) {
104045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (pud_none(*pud))
104145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			continue;
104245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
104345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		arm_smmu_free_pmds(pud);
104445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		pud++;
104545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
104645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
104745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pud_free(NULL, pud_base);
104845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
104945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
105045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_free_pgtables(struct arm_smmu_domain *smmu_domain)
105145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
105245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int i;
105344680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
105444680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	pgd_t *pgd, *pgd_base = cfg->pgd;
105545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
105645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/*
105745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * Recursively free the page tables for this domain. We don't
105834fb4b37b7b6da7dc34797d1abf234dd30b091d8Will Deacon	 * care about speculative TLB filling because the tables should
105934fb4b37b7b6da7dc34797d1abf234dd30b091d8Will Deacon	 * not be active in any context bank at this point (SCTLR.M is 0).
106045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 */
106145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pgd = pgd_base;
106245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	for (i = 0; i < PTRS_PER_PGD; ++i) {
106345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (pgd_none(*pgd))
106445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			continue;
106545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		arm_smmu_free_puds(pgd);
106645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		pgd++;
106745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
106845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
106945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	kfree(pgd_base);
107045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
107145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
107245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_domain_destroy(struct iommu_domain *domain)
107345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
107445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_domain *smmu_domain = domain->priv;
10751463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon
10761463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	/*
10771463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	 * Free the domain resources. We assume that all devices have
10781463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	 * already been detached.
10791463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon	 */
108045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	arm_smmu_destroy_domain_context(domain);
108145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	arm_smmu_free_pgtables(smmu_domain);
108245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	kfree(smmu_domain);
108345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
108445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
108545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
1086a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon					  struct arm_smmu_master_cfg *cfg)
108745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
108845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int i;
108945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_smr *smrs;
109045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
109145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
109245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH))
109345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return 0;
109445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1095a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	if (cfg->smrs)
109645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -EEXIST;
109745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
10982907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys	smrs = kmalloc_array(cfg->num_streamids, sizeof(*smrs), GFP_KERNEL);
109945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!smrs) {
1100a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		dev_err(smmu->dev, "failed to allocate %d SMRs\n",
1101a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon			cfg->num_streamids);
110245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENOMEM;
110345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
110445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
110544680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	/* Allocate the SMRs on the SMMU */
1106a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	for (i = 0; i < cfg->num_streamids; ++i) {
110745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0,
110845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon						  smmu->num_mapping_groups);
110945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (IS_ERR_VALUE(idx)) {
111045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			dev_err(smmu->dev, "failed to allocate free SMR\n");
111145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			goto err_free_smrs;
111245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
111345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
111445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		smrs[i] = (struct arm_smmu_smr) {
111545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			.idx	= idx,
111645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			.mask	= 0, /* We don't currently share SMRs */
1117a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon			.id	= cfg->streamids[i],
111845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		};
111945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
112045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
112145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* It worked! Now, poke the actual hardware */
1122a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	for (i = 0; i < cfg->num_streamids; ++i) {
112345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		u32 reg = SMR_VALID | smrs[i].id << SMR_ID_SHIFT |
112445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			  smrs[i].mask << SMR_MASK_SHIFT;
112545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_SMR(smrs[i].idx));
112645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
112745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1128a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	cfg->smrs = smrs;
112945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return 0;
113045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
113145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconerr_free_smrs:
113245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	while (--i >= 0)
113345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		__arm_smmu_free_bitmap(smmu->smr_map, smrs[i].idx);
113445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	kfree(smrs);
113545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return -ENOSPC;
113645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
113745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
113845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu,
1139a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon				      struct arm_smmu_master_cfg *cfg)
114045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
114145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int i;
114245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
1143a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	struct arm_smmu_smr *smrs = cfg->smrs;
114445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
114543b412bedb782e27a8771b61870dd45a24975266Will Deacon	if (!smrs)
114643b412bedb782e27a8771b61870dd45a24975266Will Deacon		return;
114743b412bedb782e27a8771b61870dd45a24975266Will Deacon
114845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Invalidate the SMRs before freeing back to the allocator */
1149a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	for (i = 0; i < cfg->num_streamids; ++i) {
115045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		u8 idx = smrs[i].idx;
11512907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys
115245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(idx));
115345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		__arm_smmu_free_bitmap(smmu->smr_map, idx);
115445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
115545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1156a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	cfg->smrs = NULL;
115745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	kfree(smrs);
115845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
115945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
116045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
1161a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon				      struct arm_smmu_master_cfg *cfg)
116245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
116345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int i, ret;
116444680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_device *smmu = smmu_domain->smmu;
116545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
116645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
11678f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	/* Devices in an IOMMU group may already be configured */
1168a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	ret = arm_smmu_master_configure_smrs(smmu, cfg);
116945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (ret)
11708f68f8e28298abdf518648e794c71e534eb8841cWill Deacon		return ret == -EEXIST ? 0 : ret;
117145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1172a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	for (i = 0; i < cfg->num_streamids; ++i) {
117345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		u32 idx, s2cr;
11742907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys
1175a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i];
11766069d23ce0e568909d847f28af0257b085e8e77aKefeng Wang		s2cr = S2CR_TYPE_TRANS |
117744680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		       (smmu_domain->cfg.cbndx << S2CR_CBNDX_SHIFT);
117845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx));
117945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
118045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
118145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return 0;
118245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
118345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
118445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain,
1185a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon					  struct arm_smmu_master_cfg *cfg)
118645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
118743b412bedb782e27a8771b61870dd45a24975266Will Deacon	int i;
118844680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_device *smmu = smmu_domain->smmu;
118943b412bedb782e27a8771b61870dd45a24975266Will Deacon	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
119045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
11918f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	/* An IOMMU group is torn down by the first device to be removed */
11928f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	if ((smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) && !cfg->smrs)
11938f68f8e28298abdf518648e794c71e534eb8841cWill Deacon		return;
119445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
119545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/*
119645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * We *must* clear the S2CR first, because freeing the SMR means
119745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * that it can be re-allocated immediately.
119845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 */
119943b412bedb782e27a8771b61870dd45a24975266Will Deacon	for (i = 0; i < cfg->num_streamids; ++i) {
120043b412bedb782e27a8771b61870dd45a24975266Will Deacon		u32 idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i];
120143b412bedb782e27a8771b61870dd45a24975266Will Deacon
120243b412bedb782e27a8771b61870dd45a24975266Will Deacon		writel_relaxed(S2CR_TYPE_BYPASS,
120343b412bedb782e27a8771b61870dd45a24975266Will Deacon			       gr0_base + ARM_SMMU_GR0_S2CR(idx));
120443b412bedb782e27a8771b61870dd45a24975266Will Deacon	}
120543b412bedb782e27a8771b61870dd45a24975266Will Deacon
1206a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	arm_smmu_master_free_smrs(smmu, cfg);
120745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
120845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
120945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
121045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
1211a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	int ret;
121245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_domain *smmu_domain = domain->priv;
1213a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	struct arm_smmu_device *smmu, *dom_smmu;
1214a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	struct arm_smmu_master_cfg *cfg;
121545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
12168f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	smmu = find_smmu_for_device(dev);
121744680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	if (!smmu) {
121845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n");
121945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENXIO;
122045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
122145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1222844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon	if (dev->archdata.iommu) {
1223844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon		dev_err(dev, "already attached to IOMMU domain\n");
1224844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon		return -EEXIST;
1225844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon	}
1226844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon
122745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/*
122844680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	 * Sanity check the domain. We don't support domains across
122944680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	 * different SMMUs.
123045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 */
1231a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	dom_smmu = ACCESS_ONCE(smmu_domain->smmu);
1232a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	if (!dom_smmu) {
123345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		/* Now that we have a master, we can finalise the domain */
123444680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		ret = arm_smmu_init_domain_context(domain, smmu);
123545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (IS_ERR_VALUE(ret))
1236a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys			return ret;
1237a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys
1238a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys		dom_smmu = smmu_domain->smmu;
1239a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	}
1240a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys
1241a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys	if (dom_smmu != smmu) {
124245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(dev,
124345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			"cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n",
1244a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys			dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev));
1245a18037b27ebd23edf5edad8bc6ceb72e4bb5716dMitchel Humpherys		return -EINVAL;
124645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
124745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
124845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Looks ok, so add the device to the domain */
12498f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	cfg = find_smmu_master_cfg(dev);
1250a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	if (!cfg)
125145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENODEV;
125245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1253844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon	ret = arm_smmu_domain_add_master(smmu_domain, cfg);
1254844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon	if (!ret)
1255844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon		dev->archdata.iommu = domain;
125645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return ret;
125745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
125845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
125945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)
126045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
126145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_domain *smmu_domain = domain->priv;
1262a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	struct arm_smmu_master_cfg *cfg;
126345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
12648f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	cfg = find_smmu_master_cfg(dev);
1265844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon	if (!cfg)
1266844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon		return;
1267844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon
1268844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon	dev->archdata.iommu = NULL;
1269844e35bdfe834fccb5def1bc4cd614ca22409d0cWill Deacon	arm_smmu_domain_remove_master(smmu_domain, cfg);
127045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
127145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
127245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic bool arm_smmu_pte_is_contiguous_range(unsigned long addr,
127345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon					     unsigned long end)
127445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
127545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return !(addr & ~ARM_SMMU_PTE_CONT_MASK) &&
127645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		(addr + ARM_SMMU_PTE_CONT_SIZE <= end);
127745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
127845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
127945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd,
128045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				   unsigned long addr, unsigned long end,
1281b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon				   unsigned long pfn, int prot, int stage)
128245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
128345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pte_t *pte, *start;
1284cf2d45b19ddb361241f36d8c9f3d0b234a18459bWill Deacon	pteval_t pteval = ARM_SMMU_PTE_PAGE | ARM_SMMU_PTE_AF | ARM_SMMU_PTE_XN;
128545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
128645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (pmd_none(*pmd)) {
128745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		/* Allocate a new set of tables */
1288c9d09e2748eaa55cac2af274574baa6368189bc1Will Deacon		pgtable_t table = alloc_page(GFP_ATOMIC|__GFP_ZERO);
12892907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys
129045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (!table)
129145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			return -ENOMEM;
129245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
12936dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon		arm_smmu_flush_pgtable(smmu, page_address(table), PAGE_SIZE);
129445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		pmd_populate(NULL, pmd, table);
129545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		arm_smmu_flush_pgtable(smmu, pmd, sizeof(*pmd));
129645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
129745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
129845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (stage == 1) {
12991463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon		pteval |= ARM_SMMU_PTE_AP_UNPRIV | ARM_SMMU_PTE_nG;
1300b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon		if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ))
130145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			pteval |= ARM_SMMU_PTE_AP_RDONLY;
130245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1303b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon		if (prot & IOMMU_CACHE)
130445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			pteval |= (MAIR_ATTR_IDX_CACHE <<
130545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				   ARM_SMMU_PTE_ATTRINDX_SHIFT);
130645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} else {
130745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		pteval |= ARM_SMMU_PTE_HAP_FAULT;
1308b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon		if (prot & IOMMU_READ)
130945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			pteval |= ARM_SMMU_PTE_HAP_READ;
1310b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon		if (prot & IOMMU_WRITE)
131145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			pteval |= ARM_SMMU_PTE_HAP_WRITE;
1312b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon		if (prot & IOMMU_CACHE)
131345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			pteval |= ARM_SMMU_PTE_MEMATTR_OIWB;
131445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		else
131545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			pteval |= ARM_SMMU_PTE_MEMATTR_NC;
131645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
131745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
131845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* If no access, create a faulting entry to avoid TLB fills */
1319b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon	if (prot & IOMMU_EXEC)
1320cf2d45b19ddb361241f36d8c9f3d0b234a18459bWill Deacon		pteval &= ~ARM_SMMU_PTE_XN;
1321b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon	else if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
132245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		pteval &= ~ARM_SMMU_PTE_PAGE;
132345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
132445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pteval |= ARM_SMMU_PTE_SH_IS;
132545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	start = pmd_page_vaddr(*pmd) + pte_index(addr);
132645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pte = start;
132745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
132845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/*
132945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * Install the page table entries. This is fairly complicated
133045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * since we attempt to make use of the contiguous hint in the
133145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * ptes where possible. The contiguous hint indicates a series
133245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * of ARM_SMMU_PTE_CONT_ENTRIES ptes mapping a physically
133345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * contiguous region with the following constraints:
133445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 *
133545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 *   - The region start is aligned to ARM_SMMU_PTE_CONT_SIZE
133645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 *   - Each pte in the region has the contiguous hint bit set
133745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 *
133845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * This complicates unmapping (also handled by this code, when
133945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * neither IOMMU_READ or IOMMU_WRITE are set) because it is
134045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * possible, yet highly unlikely, that a client may unmap only
134145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * part of a contiguous range. This requires clearing of the
134245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * contiguous hint bits in the range before installing the new
134345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * faulting entries.
134445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 *
134545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * Note that re-mapping an address range without first unmapping
134645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * it is not supported, so TLB invalidation is not required here
134745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 * and is instead performed at unmap and domain-init time.
134845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	 */
134945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	do {
135045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		int i = 1;
13512907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys
135245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		pteval &= ~ARM_SMMU_PTE_CONT;
135345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
135445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (arm_smmu_pte_is_contiguous_range(addr, end)) {
135545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			i = ARM_SMMU_PTE_CONT_ENTRIES;
135645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			pteval |= ARM_SMMU_PTE_CONT;
135745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		} else if (pte_val(*pte) &
135845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			   (ARM_SMMU_PTE_CONT | ARM_SMMU_PTE_PAGE)) {
135945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			int j;
136045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			pte_t *cont_start;
136145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			unsigned long idx = pte_index(addr);
136245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
136345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			idx &= ~(ARM_SMMU_PTE_CONT_ENTRIES - 1);
136445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			cont_start = pmd_page_vaddr(*pmd) + idx;
136545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			for (j = 0; j < ARM_SMMU_PTE_CONT_ENTRIES; ++j)
13662907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys				pte_val(*(cont_start + j)) &=
13672907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys					~ARM_SMMU_PTE_CONT;
136845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
136945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			arm_smmu_flush_pgtable(smmu, cont_start,
137045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon					       sizeof(*pte) *
137145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon					       ARM_SMMU_PTE_CONT_ENTRIES);
137245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
137345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
137445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		do {
137545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			*pte = pfn_pte(pfn, __pgprot(pteval));
137645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		} while (pte++, pfn++, addr += PAGE_SIZE, --i);
137745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} while (addr != end);
137845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
137945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	arm_smmu_flush_pgtable(smmu, start, sizeof(*pte) * (pte - start));
138045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return 0;
138145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
138245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
138345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud,
138445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				   unsigned long addr, unsigned long end,
1385b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon				   phys_addr_t phys, int prot, int stage)
138645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
138745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int ret;
138845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pmd_t *pmd;
138945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	unsigned long next, pfn = __phys_to_pfn(phys);
139045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
139145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#ifndef __PAGETABLE_PMD_FOLDED
139245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (pud_none(*pud)) {
1393c9d09e2748eaa55cac2af274574baa6368189bc1Will Deacon		pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC);
139445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (!pmd)
139545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			return -ENOMEM;
139697a644208d1a08b7104d1fe2ace8cef011222711Yifan Zhang
13976dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon		arm_smmu_flush_pgtable(smmu, pmd, PAGE_SIZE);
139897a644208d1a08b7104d1fe2ace8cef011222711Yifan Zhang		pud_populate(NULL, pud, pmd);
139997a644208d1a08b7104d1fe2ace8cef011222711Yifan Zhang		arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud));
140097a644208d1a08b7104d1fe2ace8cef011222711Yifan Zhang
140197a644208d1a08b7104d1fe2ace8cef011222711Yifan Zhang		pmd += pmd_index(addr);
140245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} else
140345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#endif
140445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		pmd = pmd_offset(pud, addr);
140545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
140645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	do {
140745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		next = pmd_addr_end(addr, end);
1408aca1bc4595c5757f01167ab5bfef2a4f8edfcf4fBin Wang		ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, next, pfn,
1409b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon					      prot, stage);
141045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		phys += next - addr;
1411ccd359f219bee914501a8892b148e2a1315066d3Mitchel Humpherys		pfn = __phys_to_pfn(phys);
141245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} while (pmd++, addr = next, addr < end);
141345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
141445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return ret;
141545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
141645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
141745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd,
141845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				   unsigned long addr, unsigned long end,
1419b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon				   phys_addr_t phys, int prot, int stage)
142045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
142145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int ret = 0;
142245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pud_t *pud;
142345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	unsigned long next;
142445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
142545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#ifndef __PAGETABLE_PUD_FOLDED
142645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (pgd_none(*pgd)) {
1427c9d09e2748eaa55cac2af274574baa6368189bc1Will Deacon		pud = (pud_t *)get_zeroed_page(GFP_ATOMIC);
142845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (!pud)
142945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			return -ENOMEM;
143097a644208d1a08b7104d1fe2ace8cef011222711Yifan Zhang
14316dd35f45b8dac827b6f9dd86f5aca6436cdd2410Will Deacon		arm_smmu_flush_pgtable(smmu, pud, PAGE_SIZE);
143297a644208d1a08b7104d1fe2ace8cef011222711Yifan Zhang		pgd_populate(NULL, pgd, pud);
143397a644208d1a08b7104d1fe2ace8cef011222711Yifan Zhang		arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd));
143497a644208d1a08b7104d1fe2ace8cef011222711Yifan Zhang
143597a644208d1a08b7104d1fe2ace8cef011222711Yifan Zhang		pud += pud_index(addr);
143645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} else
143745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#endif
143845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		pud = pud_offset(pgd, addr);
143945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
144045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	do {
144145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		next = pud_addr_end(addr, end);
144245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		ret = arm_smmu_alloc_init_pmd(smmu, pud, addr, next, phys,
1443b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon					      prot, stage);
144445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		phys += next - addr;
144545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} while (pud++, addr = next, addr < end);
144645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
144745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return ret;
144845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
144945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
145045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
145145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				   unsigned long iova, phys_addr_t paddr,
1452b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon				   size_t size, int prot)
145345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
145445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int ret, stage;
145545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	unsigned long end;
145645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	phys_addr_t input_mask, output_mask;
145744680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_device *smmu = smmu_domain->smmu;
145844680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
145944680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	pgd_t *pgd = cfg->pgd;
1460b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon	unsigned long flags;
146145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
146244680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	if (cfg->cbar == CBAR_TYPE_S2_TRANS) {
146345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		stage = 2;
146428d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon		input_mask = (1ULL << smmu->s2_input_size) - 1;
146545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		output_mask = (1ULL << smmu->s2_output_size) - 1;
146645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} else {
146745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		stage = 1;
146828d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon		input_mask = (1ULL << smmu->s1_input_size) - 1;
146945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		output_mask = (1ULL << smmu->s1_output_size) - 1;
147045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
147145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
147245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!pgd)
147345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -EINVAL;
147445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
147545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (size & ~PAGE_MASK)
147645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -EINVAL;
147745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
147845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if ((phys_addr_t)iova & ~input_mask)
147945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ERANGE;
148045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
148145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (paddr & ~output_mask)
148245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ERANGE;
148345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1484b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon	spin_lock_irqsave(&smmu_domain->lock, flags);
148545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	pgd += pgd_index(iova);
148645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	end = iova + size;
148745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	do {
148845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		unsigned long next = pgd_addr_end(iova, end);
148945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
149045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		ret = arm_smmu_alloc_init_pud(smmu, pgd, iova, next, paddr,
1491b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon					      prot, stage);
149245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (ret)
149345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			goto out_unlock;
149445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
149545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		paddr += next - iova;
149645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		iova = next;
149745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} while (pgd++, iova != end);
149845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
149945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconout_unlock:
1500b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon	spin_unlock_irqrestore(&smmu_domain->lock, flags);
150145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
150245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return ret;
150345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
150445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
150545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
1506b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon			phys_addr_t paddr, size_t size, int prot)
150745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
150845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_domain *smmu_domain = domain->priv;
150945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
15105552ecdbf9fb4f7608c1d7933a8baafcfa1bb337Will Deacon	if (!smmu_domain)
151145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENODEV;
151245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1513b410aed93288d0bd7650c4d17fd0f306b5082d6fWill Deacon	return arm_smmu_handle_mapping(smmu_domain, iova, paddr, size, prot);
151445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
151545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
151645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
151745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			     size_t size)
151845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
151945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int ret;
152045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_domain *smmu_domain = domain->priv;
152145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
152245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	ret = arm_smmu_handle_mapping(smmu_domain, iova, 0, size, 0);
152344680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	arm_smmu_tlb_inv_context(smmu_domain);
152416c50dcfc4c186ed09a4d80fbd511492d024a1c5Laurent Pinchart	return ret ? 0 : size;
152545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
152645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
152745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
152845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon					 dma_addr_t iova)
152945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
1530a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	pgd_t *pgdp, pgd;
1531a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	pud_t pud;
1532a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	pmd_t pmd;
1533a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	pte_t pte;
153445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_domain *smmu_domain = domain->priv;
153544680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
153645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
153744680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	pgdp = cfg->pgd;
1538a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	if (!pgdp)
1539a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon		return 0;
154045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1541a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	pgd = *(pgdp + pgd_index(iova));
1542a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	if (pgd_none(pgd))
1543a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon		return 0;
154445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1545a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	pud = *pud_offset(&pgd, iova);
1546a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	if (pud_none(pud))
1547a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon		return 0;
154845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1549a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	pmd = *pmd_offset(&pud, iova);
1550a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	if (pmd_none(pmd))
1551a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon		return 0;
155245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1553a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	pte = *(pmd_page_vaddr(pmd) + pte_index(iova));
155445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (pte_none(pte))
1555a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon		return 0;
155645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1557a44a9791e778d9ccda50d5534028ed4057a9a45bWill Deacon	return __pfn_to_phys(pte_pfn(pte)) | (iova & ~PAGE_MASK);
155845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
155945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
15601fd0c775a573646eec972a3f40563506e33d9f8aJoerg Roedelstatic bool arm_smmu_capable(enum iommu_cap cap)
156145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
1562d0948945638635487111d0851218080e81de5104Will Deacon	switch (cap) {
1563d0948945638635487111d0851218080e81de5104Will Deacon	case IOMMU_CAP_CACHE_COHERENCY:
15641fd0c775a573646eec972a3f40563506e33d9f8aJoerg Roedel		/*
15651fd0c775a573646eec972a3f40563506e33d9f8aJoerg Roedel		 * Return true here as the SMMU can always send out coherent
15661fd0c775a573646eec972a3f40563506e33d9f8aJoerg Roedel		 * requests.
15671fd0c775a573646eec972a3f40563506e33d9f8aJoerg Roedel		 */
15681fd0c775a573646eec972a3f40563506e33d9f8aJoerg Roedel		return true;
1569d0948945638635487111d0851218080e81de5104Will Deacon	case IOMMU_CAP_INTR_REMAP:
15701fd0c775a573646eec972a3f40563506e33d9f8aJoerg Roedel		return true; /* MSIs are just memory writes */
1571d0948945638635487111d0851218080e81de5104Will Deacon	default:
15721fd0c775a573646eec972a3f40563506e33d9f8aJoerg Roedel		return false;
1573d0948945638635487111d0851218080e81de5104Will Deacon	}
157445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
157545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1576a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deaconstatic int __arm_smmu_get_pci_sid(struct pci_dev *pdev, u16 alias, void *data)
1577a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon{
1578a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	*((u16 *)data) = alias;
1579a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	return 0; /* Continue walking */
158045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
158145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
15828f68f8e28298abdf518648e794c71e534eb8841cWill Deaconstatic void __arm_smmu_release_pci_iommudata(void *data)
15838f68f8e28298abdf518648e794c71e534eb8841cWill Deacon{
15848f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	kfree(data);
15858f68f8e28298abdf518648e794c71e534eb8841cWill Deacon}
15868f68f8e28298abdf518648e794c71e534eb8841cWill Deacon
158745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_add_device(struct device *dev)
158845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
1589a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	struct arm_smmu_device *smmu;
15908f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	struct arm_smmu_master_cfg *cfg;
15915fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis	struct iommu_group *group;
15928f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	void (*releasefn)(void *) = NULL;
15935fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis	int ret;
15945fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis
159544680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon	smmu = find_smmu_for_device(dev);
1596a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	if (!smmu)
159745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENODEV;
159845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
15995fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis	group = iommu_group_alloc();
16005fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis	if (IS_ERR(group)) {
16015fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis		dev_err(dev, "Failed to allocate IOMMU group\n");
16025fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis		return PTR_ERR(group);
16035fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis	}
16045fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis
1605a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	if (dev_is_pci(dev)) {
1606a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		struct pci_dev *pdev = to_pci_dev(dev);
1607a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon
1608a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
1609a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		if (!cfg) {
1610a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon			ret = -ENOMEM;
1611a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon			goto out_put_group;
1612a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		}
1613a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon
1614a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		cfg->num_streamids = 1;
1615a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		/*
1616a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		 * Assume Stream ID == Requester ID for now.
1617a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		 * We need a way to describe the ID mappings in FDT.
1618a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		 */
1619a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid,
1620a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon				       &cfg->streamids[0]);
16218f68f8e28298abdf518648e794c71e534eb8841cWill Deacon		releasefn = __arm_smmu_release_pci_iommudata;
1622a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	} else {
16238f68f8e28298abdf518648e794c71e534eb8841cWill Deacon		struct arm_smmu_master *master;
16248f68f8e28298abdf518648e794c71e534eb8841cWill Deacon
16258f68f8e28298abdf518648e794c71e534eb8841cWill Deacon		master = find_smmu_master(smmu, dev->of_node);
16268f68f8e28298abdf518648e794c71e534eb8841cWill Deacon		if (!master) {
16278f68f8e28298abdf518648e794c71e534eb8841cWill Deacon			ret = -ENODEV;
16288f68f8e28298abdf518648e794c71e534eb8841cWill Deacon			goto out_put_group;
16298f68f8e28298abdf518648e794c71e534eb8841cWill Deacon		}
16308f68f8e28298abdf518648e794c71e534eb8841cWill Deacon
16318f68f8e28298abdf518648e794c71e534eb8841cWill Deacon		cfg = &master->cfg;
1632a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	}
1633a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon
16348f68f8e28298abdf518648e794c71e534eb8841cWill Deacon	iommu_group_set_iommudata(group, cfg, releasefn);
16355fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis	ret = iommu_group_add_device(group, dev);
16365fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis
1637a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deaconout_put_group:
1638a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	iommu_group_put(group);
16395fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis	return ret;
164045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
164145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
164245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_remove_device(struct device *dev)
164345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
16445fc63a7c446e998d01a68b108fe007be675aced7Antonios Motakis	iommu_group_remove_device(dev);
164545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
164645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1647b22f6434cf48af001330e370e9d781aeb668f98cThierry Redingstatic const struct iommu_ops arm_smmu_ops = {
16481fd0c775a573646eec972a3f40563506e33d9f8aJoerg Roedel	.capable	= arm_smmu_capable,
164945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.domain_init	= arm_smmu_domain_init,
165045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.domain_destroy	= arm_smmu_domain_destroy,
165145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.attach_dev	= arm_smmu_attach_dev,
165245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.detach_dev	= arm_smmu_detach_dev,
165345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.map		= arm_smmu_map,
165445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.unmap		= arm_smmu_unmap,
165545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.iova_to_phys	= arm_smmu_iova_to_phys,
165645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.add_device	= arm_smmu_add_device,
165745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.remove_device	= arm_smmu_remove_device,
165845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.pgsize_bitmap	= (SECTION_SIZE |
165945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			   ARM_SMMU_PTE_CONT_SIZE |
166045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			   PAGE_SIZE),
166145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon};
166245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
166345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void arm_smmu_device_reset(struct arm_smmu_device *smmu)
166445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
166545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
1666659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann	void __iomem *cb_base;
166745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int i = 0;
1668659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann	u32 reg;
1669659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann
16703a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	/* clear global FSR */
16713a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
16723a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
167345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
167445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Mark all SMRn as invalid and all S2CRn as bypass */
167545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	for (i = 0; i < smmu->num_mapping_groups; ++i) {
16763c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan		writel_relaxed(0, gr0_base + ARM_SMMU_GR0_SMR(i));
16772907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys		writel_relaxed(S2CR_TYPE_BYPASS,
16782907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys			gr0_base + ARM_SMMU_GR0_S2CR(i));
167945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
168045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1681659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann	/* Make sure all context banks are disabled and clear CB_FSR  */
1682659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann	for (i = 0; i < smmu->num_context_banks; ++i) {
1683659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann		cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, i);
1684659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann		writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);
1685659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann		writel_relaxed(FSR_FAULT, cb_base + ARM_SMMU_CB_FSR);
1686659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann	}
16871463fe44fd0f87af0404e2c147ab9724081b7235Will Deacon
168845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Invalidate the TLB, just in case */
168945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	writel_relaxed(0, gr0_base + ARM_SMMU_GR0_STLBIALL);
169045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH);
169145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH);
169245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
16933a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
1694659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann
169545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Enable fault reporting */
1696659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann	reg |= (sCR0_GFRE | sCR0_GFIE | sCR0_GCFGFRE | sCR0_GCFGFIE);
169745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
169845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Disable TLB broadcasting. */
1699659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann	reg |= (sCR0_VMIDPNE | sCR0_PTM);
170045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
170145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Enable client access, but bypass when no mapping is found */
1702659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann	reg &= ~(sCR0_CLIENTPD | sCR0_USFCFG);
170345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
170445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Disable forced broadcasting */
1705659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann	reg &= ~sCR0_FB;
170645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
170745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Don't upgrade barriers */
1708659db6f6beacae6fe49b5566debc4e82f678ff63Andreas Herrmann	reg &= ~(sCR0_BSU_MASK << sCR0_BSU_SHIFT);
170945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
171045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Push the button */
171145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	arm_smmu_tlb_sync(smmu);
17123a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
171345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
171445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
171545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_id_size_to_bits(int size)
171645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
171745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	switch (size) {
171845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	case 0:
171945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return 32;
172045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	case 1:
172145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return 36;
172245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	case 2:
172345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return 40;
172445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	case 3:
172545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return 42;
172645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	case 4:
172745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return 44;
172845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	case 5:
172945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	default:
173045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return 48;
173145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
173245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
173345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
173445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
173545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
173645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	unsigned long size;
173745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
173845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	u32 id;
173945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
174045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	dev_notice(smmu->dev, "probing hardware configuration...\n");
174145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	dev_notice(smmu->dev, "SMMUv%d with:\n", smmu->version);
174245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
174345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* ID0 */
174445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID0);
174545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#ifndef CONFIG_64BIT
174645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (((id >> ID0_PTFS_SHIFT) & ID0_PTFS_MASK) == ID0_PTFS_V8_ONLY) {
174745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(smmu->dev, "\tno v7 descriptor support!\n");
174845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENODEV;
174945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
175045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#endif
17514cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will Deacon
17524cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will Deacon	/* Restrict available stages based on module parameter */
17534cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will Deacon	if (force_stage == 1)
17544cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will Deacon		id &= ~(ID0_S2TS | ID0_NTS);
17554cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will Deacon	else if (force_stage == 2)
17564cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will Deacon		id &= ~(ID0_S1TS | ID0_NTS);
17574cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will Deacon
175845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (id & ID0_S1TS) {
175945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		smmu->features |= ARM_SMMU_FEAT_TRANS_S1;
176045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_notice(smmu->dev, "\tstage 1 translation\n");
176145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
176245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
176345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (id & ID0_S2TS) {
176445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		smmu->features |= ARM_SMMU_FEAT_TRANS_S2;
176545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_notice(smmu->dev, "\tstage 2 translation\n");
176645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
176745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
176845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (id & ID0_NTS) {
176945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		smmu->features |= ARM_SMMU_FEAT_TRANS_NESTED;
177045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_notice(smmu->dev, "\tnested translation\n");
177145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
177245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
177345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!(smmu->features &
17744cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5Will Deacon		(ARM_SMMU_FEAT_TRANS_S1 | ARM_SMMU_FEAT_TRANS_S2))) {
177545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(smmu->dev, "\tno translation support!\n");
177645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENODEV;
177745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
177845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
177945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (id & ID0_CTTW) {
178045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
178145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_notice(smmu->dev, "\tcoherent table walk\n");
178245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
178345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
178445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (id & ID0_SMS) {
178545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		u32 smr, sid, mask;
178645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
178745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		smmu->features |= ARM_SMMU_FEAT_STREAM_MATCH;
178845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		smmu->num_mapping_groups = (id >> ID0_NUMSMRG_SHIFT) &
178945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon					   ID0_NUMSMRG_MASK;
179045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (smmu->num_mapping_groups == 0) {
179145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			dev_err(smmu->dev,
179245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				"stream-matching supported, but no SMRs present!\n");
179345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			return -ENODEV;
179445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
179545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
179645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		smr = SMR_MASK_MASK << SMR_MASK_SHIFT;
179745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		smr |= (SMR_ID_MASK << SMR_ID_SHIFT);
179845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
179945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
180045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
180145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		mask = (smr >> SMR_MASK_SHIFT) & SMR_MASK_MASK;
180245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		sid = (smr >> SMR_ID_SHIFT) & SMR_ID_MASK;
180345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if ((mask & sid) != sid) {
180445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			dev_err(smmu->dev,
180545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				"SMR mask bits (0x%x) insufficient for ID field (0x%x)\n",
180645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				mask, sid);
180745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			return -ENODEV;
180845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
180945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
181045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_notice(smmu->dev,
181145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			   "\tstream matching with %u register groups, mask 0x%x",
181245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			   smmu->num_mapping_groups, mask);
18133c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan	} else {
18143c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan		smmu->num_mapping_groups = (id >> ID0_NUMSIDB_SHIFT) &
18153c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan					   ID0_NUMSIDB_MASK;
181645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
181745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
181845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* ID1 */
181945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID1);
1820c757e8528a304214d0a9be2e99011b94bf374d37Will Deacon	smmu->pgshift = (id & ID1_PAGESIZE) ? 16 : 12;
182145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1822c55af7f719cbb0f0b28f42b3f98f662278f063c2Andreas Herrmann	/* Check for size mismatch of SMMU address space from mapped region */
18232907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys	size = 1 <<
18242907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys		(((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1);
1825c757e8528a304214d0a9be2e99011b94bf374d37Will Deacon	size *= 2 << smmu->pgshift;
1826c55af7f719cbb0f0b28f42b3f98f662278f063c2Andreas Herrmann	if (smmu->size != size)
18272907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys		dev_warn(smmu->dev,
18282907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys			"SMMU address space size (0x%lx) differs from mapped region size (0x%lx)!\n",
18292907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys			size, smmu->size);
183045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
183145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	smmu->num_s2_context_banks = (id >> ID1_NUMS2CB_SHIFT) &
183245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				      ID1_NUMS2CB_MASK;
183345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	smmu->num_context_banks = (id >> ID1_NUMCB_SHIFT) & ID1_NUMCB_MASK;
183445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (smmu->num_s2_context_banks > smmu->num_context_banks) {
183545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(smmu->dev, "impossible number of S2 context banks!\n");
183645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENODEV;
183745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
183845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	dev_notice(smmu->dev, "\t%u context banks (%u stage-2 only)\n",
183945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		   smmu->num_context_banks, smmu->num_s2_context_banks);
184045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
184145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* ID2 */
184245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID2);
184345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	size = arm_smmu_id_size_to_bits((id >> ID2_IAS_SHIFT) & ID2_IAS_MASK);
184428d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon	smmu->s1_output_size = min_t(unsigned long, PHYS_MASK_SHIFT, size);
184545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
184628d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon	/* Stage-2 input size limited due to pgd allocation (PTRS_PER_PGD) */
184745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#ifdef CONFIG_64BIT
184828d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon	smmu->s2_input_size = min_t(unsigned long, VA_BITS, size);
184945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#else
185028d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon	smmu->s2_input_size = min(32UL, size);
185145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#endif
185245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
185345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* The stage-2 output mask is also applied for bypass */
185445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK);
18552907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys	smmu->s2_output_size = min_t(unsigned long, PHYS_MASK_SHIFT, size);
185645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1857093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	if (smmu->version == ARM_SMMU_V1) {
185828d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon		smmu->s1_input_size = 32;
185945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	} else {
186045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#ifdef CONFIG_64BIT
186145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		size = (id >> ID2_UBS_SHIFT) & ID2_UBS_MASK;
186206f983dd571f564bdd3eb2ac4c33002034ea7810Will Deacon		size = min(VA_BITS, arm_smmu_id_size_to_bits(size));
186345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#else
186445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		size = 32;
186545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon#endif
186628d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon		smmu->s1_input_size = size;
186745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
186845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if ((PAGE_SIZE == SZ_4K && !(id & ID2_PTFS_4K)) ||
186945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		    (PAGE_SIZE == SZ_64K && !(id & ID2_PTFS_64K)) ||
187045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		    (PAGE_SIZE != SZ_4K && PAGE_SIZE != SZ_64K)) {
187145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			dev_err(smmu->dev, "CPU page size 0x%lx unsupported\n",
187245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				PAGE_SIZE);
187345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			return -ENODEV;
187445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
187545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
187645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
187728d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon	if (smmu->features & ARM_SMMU_FEAT_TRANS_S1)
187828d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon		dev_notice(smmu->dev, "\tStage-1: %lu-bit VA -> %lu-bit IPA\n",
187928d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon			   smmu->s1_input_size, smmu->s1_output_size);
188028d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon
188128d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon	if (smmu->features & ARM_SMMU_FEAT_TRANS_S2)
188228d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon		dev_notice(smmu->dev, "\tStage-2: %lu-bit IPA -> %lu-bit PA\n",
188328d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon			   smmu->s2_input_size, smmu->s2_output_size);
188428d6007ba2fd344164e01ef300af7f621e9e6b0dWill Deacon
188545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return 0;
188645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
188745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
188809b5269a1b3d47525d7c25efeb16f5407ef82ea2Joerg Roedelstatic const struct of_device_id arm_smmu_of_match[] = {
1889093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	{ .compatible = "arm,smmu-v1", .data = (void *)ARM_SMMU_V1 },
1890093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	{ .compatible = "arm,smmu-v2", .data = (void *)ARM_SMMU_V2 },
1891093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	{ .compatible = "arm,mmu-400", .data = (void *)ARM_SMMU_V1 },
1892d3aba0460a2e13b49892f7a12237f82658c44257Robin Murphy	{ .compatible = "arm,mmu-401", .data = (void *)ARM_SMMU_V1 },
1893093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	{ .compatible = "arm,mmu-500", .data = (void *)ARM_SMMU_V2 },
1894093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	{ },
1895093604033361928f7f355b4d1766d0179ae747fbRobin Murphy};
1896093604033361928f7f355b4d1766d0179ae747fbRobin MurphyMODULE_DEVICE_TABLE(of, arm_smmu_of_match);
1897093604033361928f7f355b4d1766d0179ae747fbRobin Murphy
189845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_device_dt_probe(struct platform_device *pdev)
189945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
1900093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	const struct of_device_id *of_id;
190145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct resource *res;
190245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_device *smmu;
190345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct device *dev = &pdev->dev;
190445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct rb_node *node;
190545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct of_phandle_args masterspec;
190645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int num_irqs, i, err;
190745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
190845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
190945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!smmu) {
191045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(dev, "failed to allocate arm_smmu_device\n");
191145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENOMEM;
191245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
191345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	smmu->dev = dev;
191445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
1915093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	of_id = of_match_node(arm_smmu_of_match, dev->of_node);
1916093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	smmu->version = (enum arm_smmu_arch_version)of_id->data;
1917093604033361928f7f355b4d1766d0179ae747fbRobin Murphy
191845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
19198a7f431221602fcde573dfdba26de1990ec195a0Julia Lawall	smmu->base = devm_ioremap_resource(dev, res);
19208a7f431221602fcde573dfdba26de1990ec195a0Julia Lawall	if (IS_ERR(smmu->base))
19218a7f431221602fcde573dfdba26de1990ec195a0Julia Lawall		return PTR_ERR(smmu->base);
192245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	smmu->size = resource_size(res);
192345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
192445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (of_property_read_u32(dev->of_node, "#global-interrupts",
192545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				 &smmu->num_global_irqs)) {
192645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(dev, "missing #global-interrupts property\n");
192745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENODEV;
192845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
192945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
193045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	num_irqs = 0;
193145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs))) {
193245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		num_irqs++;
193345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (num_irqs > smmu->num_global_irqs)
193445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			smmu->num_context_irqs++;
193545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
193645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
193744a08de2aaf7f4cf86dfcf04bee32536e4a2b5b8Andreas Herrmann	if (!smmu->num_context_irqs) {
193844a08de2aaf7f4cf86dfcf04bee32536e4a2b5b8Andreas Herrmann		dev_err(dev, "found %d interrupts but expected at least %d\n",
193944a08de2aaf7f4cf86dfcf04bee32536e4a2b5b8Andreas Herrmann			num_irqs, smmu->num_global_irqs + 1);
194044a08de2aaf7f4cf86dfcf04bee32536e4a2b5b8Andreas Herrmann		return -ENODEV;
194145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
194245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
194345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	smmu->irqs = devm_kzalloc(dev, sizeof(*smmu->irqs) * num_irqs,
194445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				  GFP_KERNEL);
194545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!smmu->irqs) {
194645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(dev, "failed to allocate %d irqs\n", num_irqs);
194745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENOMEM;
194845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
194945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
195045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	for (i = 0; i < num_irqs; ++i) {
195145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		int irq = platform_get_irq(pdev, i);
19522907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys
195345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (irq < 0) {
195445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			dev_err(dev, "failed to get irq index %d\n", i);
195545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			return -ENODEV;
195645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
195745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		smmu->irqs[i] = irq;
195845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
195945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
19603c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan	err = arm_smmu_device_cfg_probe(smmu);
19613c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan	if (err)
19623c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan		return err;
19633c8766d0ca9618a406b0a1ecc29147820e93d984Olav Haugan
196445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	i = 0;
196545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	smmu->masters = RB_ROOT;
196645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	while (!of_parse_phandle_with_args(dev->of_node, "mmu-masters",
196745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon					   "#stream-id-cells", i,
196845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon					   &masterspec)) {
196945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		err = register_smmu_master(smmu, dev, &masterspec);
197045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (err) {
197145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			dev_err(dev, "failed to add master %s\n",
197245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				masterspec.np->name);
197345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			goto out_put_masters;
197445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
197545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
197645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		i++;
197745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
197845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	dev_notice(dev, "registered %d master devices\n", i);
197945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
19803a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann	parse_driver_options(smmu);
19813a5df8ff35a28bfc0a3662a5906af2c98d4807d8Andreas Herrmann
1982093604033361928f7f355b4d1766d0179ae747fbRobin Murphy	if (smmu->version > ARM_SMMU_V1 &&
198345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	    smmu->num_context_banks != smmu->num_context_irqs) {
198445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(dev,
198545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			"found only %d context interrupt(s) but %d required\n",
198645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			smmu->num_context_irqs, smmu->num_context_banks);
198789a23cde75a7f0b3d8b0c156964eca0c23d2f1ebWei Yongjun		err = -ENODEV;
198844680eedf9409daf0fed618ae101f35d1f83d1a4Will Deacon		goto out_put_masters;
198945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
199045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
199145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	for (i = 0; i < smmu->num_global_irqs; ++i) {
199245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		err = request_irq(smmu->irqs[i],
199345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				  arm_smmu_global_fault,
199445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				  IRQF_SHARED,
199545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				  "arm-smmu global fault",
199645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				  smmu);
199745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (err) {
199845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			dev_err(dev, "failed to request global IRQ %d (%u)\n",
199945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon				i, smmu->irqs[i]);
200045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			goto out_free_irqs;
200145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
200245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
200345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
200445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	INIT_LIST_HEAD(&smmu->list);
200545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	spin_lock(&arm_smmu_devices_lock);
200645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	list_add(&smmu->list, &arm_smmu_devices);
200745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	spin_unlock(&arm_smmu_devices_lock);
2008fd90cecbde065eac6ecc3ef38abace725ad27010Will Deacon
2009fd90cecbde065eac6ecc3ef38abace725ad27010Will Deacon	arm_smmu_device_reset(smmu);
201045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return 0;
201145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
201245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconout_free_irqs:
201345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	while (i--)
201445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		free_irq(smmu->irqs[i], smmu);
201545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
201645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconout_put_masters:
201745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	for (node = rb_first(&smmu->masters); node; node = rb_next(node)) {
20182907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys		struct arm_smmu_master *master
20192907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys			= container_of(node, struct arm_smmu_master, node);
202045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		of_node_put(master->of_node);
202145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
202245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
202345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return err;
202445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
202545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
202645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int arm_smmu_device_remove(struct platform_device *pdev)
202745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
202845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int i;
202945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct device *dev = &pdev->dev;
203045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct arm_smmu_device *curr, *smmu = NULL;
203145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	struct rb_node *node;
203245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
203345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	spin_lock(&arm_smmu_devices_lock);
203445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	list_for_each_entry(curr, &arm_smmu_devices, list) {
203545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		if (curr->dev == dev) {
203645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			smmu = curr;
203745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			list_del(&smmu->list);
203845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon			break;
203945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		}
204045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
204145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	spin_unlock(&arm_smmu_devices_lock);
204245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
204345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (!smmu)
204445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return -ENODEV;
204545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
204645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	for (node = rb_first(&smmu->masters); node; node = rb_next(node)) {
20472907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys		struct arm_smmu_master *master
20482907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys			= container_of(node, struct arm_smmu_master, node);
204945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		of_node_put(master->of_node);
205045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	}
205145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
2052ecfadb6e5b49a0a56df2038bf39f1fcd652788b9Will Deacon	if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS))
205345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		dev_err(dev, "removing device with active domains!\n");
205445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
205545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	for (i = 0; i < smmu->num_global_irqs; ++i)
205645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		free_irq(smmu->irqs[i], smmu);
205745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
205845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Turn the thing off */
20592907320df3189420cb66178a86b2917f4b64018fMitchel Humpherys	writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
206045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return 0;
206145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
206245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
206345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic struct platform_driver arm_smmu_driver = {
206445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.driver	= {
206545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		.owner		= THIS_MODULE,
206645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		.name		= "arm-smmu",
206745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		.of_match_table	= of_match_ptr(arm_smmu_of_match),
206845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	},
206945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.probe	= arm_smmu_device_dt_probe,
207045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	.remove	= arm_smmu_device_remove,
207145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon};
207245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
207345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic int __init arm_smmu_init(void)
207445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
207545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	int ret;
207645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
207745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	ret = platform_driver_register(&arm_smmu_driver);
207845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	if (ret)
207945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		return ret;
208045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
208145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	/* Oh, for a proper bus abstraction */
20826614ee77f49d37f9bb77eb3e81431ca8fcc4042eDan Carpenter	if (!iommu_present(&platform_bus_type))
208345ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
208445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
2085d123cf82d339c5cc4ffe2a481e0caa23a501d4acWill Deacon#ifdef CONFIG_ARM_AMBA
20866614ee77f49d37f9bb77eb3e81431ca8fcc4042eDan Carpenter	if (!iommu_present(&amba_bustype))
208745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon		bus_set_iommu(&amba_bustype, &arm_smmu_ops);
2088d123cf82d339c5cc4ffe2a481e0caa23a501d4acWill Deacon#endif
208945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
2090a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon#ifdef CONFIG_PCI
2091a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon	if (!iommu_present(&pci_bus_type))
2092a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon		bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
2093a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon#endif
2094a9a1b0b53d8b7ca60abef0687eae927f286f07c2Will Deacon
209545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return 0;
209645ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
209745ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
209845ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconstatic void __exit arm_smmu_exit(void)
209945ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon{
210045ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon	return platform_driver_unregister(&arm_smmu_driver);
210145ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon}
210245ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
2103b1950b2796da80b66df02db39cc3417266b73767Andreas Herrmannsubsys_initcall(arm_smmu_init);
210445ae7cff3684ab45f57fc13fc242c8546536a84eWill Deaconmodule_exit(arm_smmu_exit);
210545ae7cff3684ab45f57fc13fc242c8546536a84eWill Deacon
210645ae7cff3684ab45f57fc13fc242c8546536a84eWill DeaconMODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");
210745ae7cff3684ab45f57fc13fc242c8546536a84eWill DeaconMODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
210845ae7cff3684ab45f57fc13fc242c8546536a84eWill DeaconMODULE_LICENSE("GPL v2");
2109