xref: /arm-trusted-firmware/plat/brcm/board/stingray/src/iommu.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2017 - 2020, Broadcom
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <arch_helpers.h>
8*91f16700Schasinglulu #include <common/debug.h>
9*91f16700Schasinglulu #include <drivers/delay_timer.h>
10*91f16700Schasinglulu #include <lib/mmio.h>
11*91f16700Schasinglulu 
12*91f16700Schasinglulu #include <iommu.h>
13*91f16700Schasinglulu #include <platform_def.h>
14*91f16700Schasinglulu 
15*91f16700Schasinglulu #define SMMU_BASE		0x64000000
16*91f16700Schasinglulu #define ARM_SMMU_MAX_NUM_CNTXT_BANK	64
17*91f16700Schasinglulu #define SMMU_CTX_BANK_IDX_SECURE_CRMU	63
18*91f16700Schasinglulu #define ARM_SMMU_NUM_SECURE_MASTER	1
19*91f16700Schasinglulu #define ARM_SMMU_NSNUMCBO		(ARM_SMMU_MAX_NUM_CNTXT_BANK - \
20*91f16700Schasinglulu 					 ARM_SMMU_NUM_SECURE_MASTER)
21*91f16700Schasinglulu #define ARM_SMMU_NSNUMSMRGO		(ARM_SMMU_MAX_NUM_CNTXT_BANK - \
22*91f16700Schasinglulu 					 ARM_SMMU_NUM_SECURE_MASTER)
23*91f16700Schasinglulu /* Reserved Banks. */
24*91f16700Schasinglulu #define SMMU_CTX_BANK_IDX		(SMMU_CTX_BANK_IDX_SECURE_CRMU - \
25*91f16700Schasinglulu 					 ARM_SMMU_NUM_SECURE_MASTER)
26*91f16700Schasinglulu #define NUM_OF_SMRS			1
27*91f16700Schasinglulu 
28*91f16700Schasinglulu #define STG1_WITH_STG2_BYPASS		1
29*91f16700Schasinglulu #define ARM_LPAE_PGTBL_PHYS_CRMU	0x880000000
30*91f16700Schasinglulu #define ARM_LPAE_PGTBL_PHYS		0x880200000
31*91f16700Schasinglulu #define ARM_LPAE_PGTBL_PTE_CNT		512
32*91f16700Schasinglulu #define ARM_LPAE_PTE_L1_BLOCK_SIZE	0x40000000
33*91f16700Schasinglulu #define ARM_LPAE_PTE_L1_ADDR_MASK	0x0000FFFFC0000000UL
34*91f16700Schasinglulu #define ARM_LPAE_PTE_TABLE		0x2UL
35*91f16700Schasinglulu #define ARM_LPAE_PTE_VALID		0x1UL
36*91f16700Schasinglulu #define ARM_LPAE_PTE_ATTRINDX		2
37*91f16700Schasinglulu #define ARM_LPAE_PTE_NS			5
38*91f16700Schasinglulu #define ARM_LPAE_PTE_AP			6
39*91f16700Schasinglulu #define ARM_LPAE_PTE_AP_EL1_RW		0x0
40*91f16700Schasinglulu #define ARM_LPAE_PTE_AP_EL0_RW		0x1
41*91f16700Schasinglulu #define ARM_LPAE_PTE_SH			8
42*91f16700Schasinglulu #define ARM_LPAE_PTE_SH_NON		0x0
43*91f16700Schasinglulu #define ARM_LPAE_PTE_SH_OUTER		0x2
44*91f16700Schasinglulu #define ARM_LPAE_PTE_SH_INNER		0x3
45*91f16700Schasinglulu #define ARM_LPAE_PTE_AF			10
46*91f16700Schasinglulu #define ARM_SMMU_RES_SIZE		0x80000
47*91f16700Schasinglulu 
48*91f16700Schasinglulu #define ARM_LPAE_PTE_NSTABLE		0x8000000000000000UL
49*91f16700Schasinglulu #define ARM_LPAE_PTE_L1_INDEX_SHIFT	30
50*91f16700Schasinglulu #define ARM_LPAE_PTE_L1_INDEX_MASK	0x1ff
51*91f16700Schasinglulu #define ARM_LPAE_PTE_L0_INDEX_SHIFT	39
52*91f16700Schasinglulu #define ARM_LPAE_PTE_L0_INDEX_MASK	0x1ff
53*91f16700Schasinglulu #define ARM_LPAE_PTE_TABLE_MASK		~(0xfffUL)
54*91f16700Schasinglulu /* Configuration registers */
55*91f16700Schasinglulu #define ARM_SMMU_GR0_sCR0	0x0
56*91f16700Schasinglulu #define sCR0_CLIENTPD		(1 << 0)
57*91f16700Schasinglulu #define sCR0_GFRE		(1 << 1)
58*91f16700Schasinglulu #define sCR0_GFIE		(1 << 2)
59*91f16700Schasinglulu #define sCR0_GCFGFRE		(1 << 4)
60*91f16700Schasinglulu #define sCR0_GCFGFIE		(1 << 5)
61*91f16700Schasinglulu #define sCR0_USFCFG		(1 << 10)
62*91f16700Schasinglulu #define sCR0_VMIDPNE		(1 << 11)
63*91f16700Schasinglulu #define sCR0_PTM		(1 << 12)
64*91f16700Schasinglulu #define sCR0_FB			(1 << 13)
65*91f16700Schasinglulu #define sCR0_VMID16EN		(1 << 31)
66*91f16700Schasinglulu #define sCR0_BSU_SHIFT		14
67*91f16700Schasinglulu #define sCR0_BSU_MASK		0x3
68*91f16700Schasinglulu #define ARM_SMMU_SMMU_SCR1	0x4
69*91f16700Schasinglulu #define SCR1_NSNUMCBO_MASK	0xFF
70*91f16700Schasinglulu #define SCR1_NSNUMCBO_SHIFT	0x0
71*91f16700Schasinglulu #define SCR1_NSNUMSMRGO_MASK	0xFF00
72*91f16700Schasinglulu #define SCR1_NSNUMSMRGO_SHIFT	0x8
73*91f16700Schasinglulu 
74*91f16700Schasinglulu /* Identification registers */
75*91f16700Schasinglulu #define ARM_SMMU_GR0_ID0		0x20
76*91f16700Schasinglulu #define ARM_SMMU_GR0_ID1		0x24
77*91f16700Schasinglulu #define ARM_SMMU_GR0_ID2		0x28
78*91f16700Schasinglulu #define ARM_SMMU_GR0_ID3		0x2c
79*91f16700Schasinglulu #define ARM_SMMU_GR0_ID4		0x30
80*91f16700Schasinglulu #define ARM_SMMU_GR0_ID5		0x34
81*91f16700Schasinglulu #define ARM_SMMU_GR0_ID6		0x38
82*91f16700Schasinglulu #define ARM_SMMU_GR0_ID7		0x3c
83*91f16700Schasinglulu #define ARM_SMMU_GR0_sGFSR		0x48
84*91f16700Schasinglulu #define ARM_SMMU_GR0_sGFSYNR0		0x50
85*91f16700Schasinglulu #define ARM_SMMU_GR0_sGFSYNR1		0x54
86*91f16700Schasinglulu #define ARM_SMMU_GR0_sGFSYNR2		0x58
87*91f16700Schasinglulu 
88*91f16700Schasinglulu #define ID1_PAGESIZE			(1U << 31)
89*91f16700Schasinglulu #define ID1_NUMPAGENDXB_SHIFT		28
90*91f16700Schasinglulu #define ID1_NUMPAGENDXB_MASK		7
91*91f16700Schasinglulu #define ID1_NUMS2CB_SHIFT		16
92*91f16700Schasinglulu #define ID1_NUMS2CB_MASK		0xff
93*91f16700Schasinglulu #define ID1_NUMCB_SHIFT			0
94*91f16700Schasinglulu #define ID1_NUMCB_MASK			0xff
95*91f16700Schasinglulu 
96*91f16700Schasinglulu /* SMMU global address space */
97*91f16700Schasinglulu #define ARM_SMMU_GR0(smmu)	((smmu)->base)
98*91f16700Schasinglulu #define ARM_SMMU_GR1(smmu)	((smmu)->base + (1 << (smmu)->pgshift))
99*91f16700Schasinglulu 
100*91f16700Schasinglulu /* Stream mapping registers */
101*91f16700Schasinglulu #define ARM_SMMU_GR0_SMR(n)	(0x800 + (n << 2))
102*91f16700Schasinglulu #define SMR_VALID		(1U << 31)
103*91f16700Schasinglulu #define SMR_MASK_SHIFT		16
104*91f16700Schasinglulu #define SMR_ID_SHIFT		0
105*91f16700Schasinglulu 
106*91f16700Schasinglulu #define ARM_SMMU_GR0_S2CR(n)	(0xc00 + (n << 2))
107*91f16700Schasinglulu #define S2CR_CBNDX_SHIFT	0
108*91f16700Schasinglulu #define S2CR_CBNDX_MASK		0xff
109*91f16700Schasinglulu #define S2CR_TYPE_SHIFT		16
110*91f16700Schasinglulu #define S2CR_TYPE_MASK		0x3
111*91f16700Schasinglulu 
112*91f16700Schasinglulu #define ARM_SMMU_GR1_CBA2R(n)	(0x800 + (n << 2))
113*91f16700Schasinglulu #define CBA2R_RW64_32BIT	(0 << 0)
114*91f16700Schasinglulu #define CBA2R_RW64_64BIT	(1 << 0)
115*91f16700Schasinglulu #define CBA2R_VMID_SHIFT	16
116*91f16700Schasinglulu #define CBA2R_VMID_MASK		0xffff
117*91f16700Schasinglulu 
118*91f16700Schasinglulu #define ARM_SMMU_GR1_CBAR(n)	(0x0 + (n << 2))
119*91f16700Schasinglulu #define CBAR_VMID_SHIFT		0
120*91f16700Schasinglulu #define CBAR_VMID_MASK		0xff
121*91f16700Schasinglulu #define CBAR_S1_BPSHCFG_SHIFT	8
122*91f16700Schasinglulu #define CBAR_S1_BPSHCFG_MASK	3
123*91f16700Schasinglulu #define CBAR_S1_BPSHCFG_NSH	3
124*91f16700Schasinglulu #define CBAR_S1_MEMATTR_SHIFT	12
125*91f16700Schasinglulu #define CBAR_S1_MEMATTR_MASK	0xf
126*91f16700Schasinglulu #define CBAR_S1_MEMATTR_WB	0xf
127*91f16700Schasinglulu #define CBAR_TYPE_SHIFT		16
128*91f16700Schasinglulu #define CBAR_TYPE_MASK		0x3
129*91f16700Schasinglulu #define CBAR_TYPE_S2_TRANS		(0 << CBAR_TYPE_SHIFT)
130*91f16700Schasinglulu #define CBAR_TYPE_S1_TRANS_S2_BYPASS	(1 << CBAR_TYPE_SHIFT)
131*91f16700Schasinglulu #define CBAR_TYPE_S1_TRANS_S2_FAULT	(2 << CBAR_TYPE_SHIFT)
132*91f16700Schasinglulu #define CBAR_TYPE_S1_TRANS_S2_TRANS	(3 << CBAR_TYPE_SHIFT)
133*91f16700Schasinglulu #define CBAR_IRPTNDX_SHIFT		24
134*91f16700Schasinglulu #define CBAR_IRPTNDX_MASK		0xff
135*91f16700Schasinglulu 
136*91f16700Schasinglulu /* Translation context bank */
137*91f16700Schasinglulu #define ARM_SMMU_CB_BASE(smmu)		((smmu)->base + ((smmu)->size >> 1))
138*91f16700Schasinglulu #define ARM_SMMU_CB(smmu, n)		((n) * (1 << (smmu)->pgshift))
139*91f16700Schasinglulu 
140*91f16700Schasinglulu #define ARM_SMMU_CB_SCTLR		0x0
141*91f16700Schasinglulu #define ARM_SMMU_CB_ACTLR		0x4
142*91f16700Schasinglulu #define ARM_SMMU_CB_RESUME		0x8
143*91f16700Schasinglulu #define ARM_SMMU_CB_TTBCR2		0x10
144*91f16700Schasinglulu #define ARM_SMMU_CB_TTBR0		0x20
145*91f16700Schasinglulu #define ARM_SMMU_CB_TTBR1		0x28
146*91f16700Schasinglulu #define ARM_SMMU_CB_TTBCR		0x30
147*91f16700Schasinglulu #define ARM_SMMU_CB_CONTEXTIDR		0x34
148*91f16700Schasinglulu #define ARM_SMMU_CB_S1_MAIR0		0x38
149*91f16700Schasinglulu #define ARM_SMMU_CB_S1_MAIR1		0x3c
150*91f16700Schasinglulu #define ARM_SMMU_CB_PAR			0x50
151*91f16700Schasinglulu #define ARM_SMMU_CB_FSR			0x58
152*91f16700Schasinglulu #define ARM_SMMU_CB_FAR			0x60
153*91f16700Schasinglulu #define ARM_SMMU_CB_FSYNR0		0x68
154*91f16700Schasinglulu #define ARM_SMMU_CB_S1_TLBIVA		0x600
155*91f16700Schasinglulu #define ARM_SMMU_CB_S1_TLBIASID		0x610
156*91f16700Schasinglulu #define ARM_SMMU_CB_S1_TLBIVAL		0x620
157*91f16700Schasinglulu #define ARM_SMMU_CB_S2_TLBIIPAS2	0x630
158*91f16700Schasinglulu #define ARM_SMMU_CB_S2_TLBIIPAS2L	0x638
159*91f16700Schasinglulu #define ARM_SMMU_CB_ATS1PR		0x800
160*91f16700Schasinglulu #define ARM_SMMU_CB_ATSR		0x8f0
161*91f16700Schasinglulu 
162*91f16700Schasinglulu #define SCTLR_S1_ASIDPNE		(1 << 12)
163*91f16700Schasinglulu #define SCTLR_CFCFG			(1 << 7)
164*91f16700Schasinglulu #define SCTLR_CFIE			(1 << 6)
165*91f16700Schasinglulu #define SCTLR_CFRE			(1 << 5)
166*91f16700Schasinglulu #define SCTLR_E				(1 << 4)
167*91f16700Schasinglulu #define SCTLR_AFE			(1 << 2)
168*91f16700Schasinglulu #define SCTLR_TRE			(1 << 1)
169*91f16700Schasinglulu #define SCTLR_M				(1 << 0)
170*91f16700Schasinglulu 
171*91f16700Schasinglulu /* ARM LPAE configuration. */
172*91f16700Schasinglulu /**************************************************************/
173*91f16700Schasinglulu /* Register bits */
174*91f16700Schasinglulu #define ARM_32_LPAE_TCR_EAE		(1 << 31)
175*91f16700Schasinglulu #define ARM_64_LPAE_S2_TCR_RES1		(1 << 31)
176*91f16700Schasinglulu 
177*91f16700Schasinglulu #define ARM_LPAE_TCR_EPD1		(1 << 23)
178*91f16700Schasinglulu 
179*91f16700Schasinglulu #define ARM_LPAE_TCR_TG0_4K		(0 << 14)
180*91f16700Schasinglulu #define ARM_LPAE_TCR_TG0_64K		(1 << 14)
181*91f16700Schasinglulu #define ARM_LPAE_TCR_TG0_16K		(2 << 14)
182*91f16700Schasinglulu 
183*91f16700Schasinglulu #define ARM_LPAE_TCR_SH0_SHIFT		12
184*91f16700Schasinglulu #define ARM_LPAE_TCR_SH0_MASK		0x3
185*91f16700Schasinglulu #define ARM_LPAE_TCR_SH_NS		0
186*91f16700Schasinglulu #define ARM_LPAE_TCR_SH_OS		2
187*91f16700Schasinglulu #define ARM_LPAE_TCR_SH_IS		3
188*91f16700Schasinglulu 
189*91f16700Schasinglulu #define ARM_LPAE_TCR_ORGN0_SHIFT	10
190*91f16700Schasinglulu #define ARM_LPAE_TCR_IRGN0_SHIFT	8
191*91f16700Schasinglulu #define ARM_LPAE_TCR_RGN_MASK		0x3
192*91f16700Schasinglulu #define ARM_LPAE_TCR_RGN_NC		0
193*91f16700Schasinglulu #define ARM_LPAE_TCR_RGN_WBWA		1
194*91f16700Schasinglulu #define ARM_LPAE_TCR_RGN_WT		2
195*91f16700Schasinglulu #define ARM_LPAE_TCR_RGN_WB		3
196*91f16700Schasinglulu 
197*91f16700Schasinglulu #define ARM_LPAE_TCR_SL0_SHIFT		6
198*91f16700Schasinglulu #define ARM_LPAE_TCR_SL0_MASK		0x3
199*91f16700Schasinglulu 
200*91f16700Schasinglulu #define ARM_LPAE_TCR_T0SZ_SHIFT		0
201*91f16700Schasinglulu #define ARM_LPAE_TCR_SZ_MASK		0xf
202*91f16700Schasinglulu 
203*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_SHIFT		16
204*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_MASK		0x7
205*91f16700Schasinglulu 
206*91f16700Schasinglulu #define ARM_LPAE_TCR_IPS_SHIFT		32
207*91f16700Schasinglulu #define ARM_LPAE_TCR_IPS_MASK		0x7
208*91f16700Schasinglulu 
209*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_32_BIT		0x0ULL
210*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_36_BIT		0x1ULL
211*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_40_BIT		0x2ULL
212*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_42_BIT		0x3ULL
213*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_44_BIT		0x4ULL
214*91f16700Schasinglulu #define ARM_LPAE_TCR_PS_48_BIT		0x5ULL
215*91f16700Schasinglulu 
216*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_SHIFT(n)	((n) << 3)
217*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_MASK		0xff
218*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_DEVICE	0x04
219*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_NC		0x44
220*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_WBRWA	0xff
221*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_IDX_NC	0
222*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_IDX_CACHE	1
223*91f16700Schasinglulu #define ARM_LPAE_MAIR_ATTR_IDX_DEV	2
224*91f16700Schasinglulu 
225*91f16700Schasinglulu #define TTBRn_ASID_SHIFT		48
226*91f16700Schasinglulu #define TTBCR2_SEP_SHIFT		15
227*91f16700Schasinglulu #define TTBCR2_SEP_UPSTREAM		(0x7 << TTBCR2_SEP_SHIFT)
228*91f16700Schasinglulu #define TTBCR2_AS                       (1 << 4)
229*91f16700Schasinglulu #define TTBCR_T0SZ(ia_bits)		(64 - (ia_bits))
230*91f16700Schasinglulu 
231*91f16700Schasinglulu #define S2CR_PRIVCFG_SHIFT		24
232*91f16700Schasinglulu #define S2CR_PRIVCFG_MASK		0x3
233*91f16700Schasinglulu 
234*91f16700Schasinglulu /**************************************************************/
235*91f16700Schasinglulu 
236*91f16700Schasinglulu uint16_t paxc_stream_ids[] = { 0x2000 };
237*91f16700Schasinglulu 
238*91f16700Schasinglulu uint16_t paxc_stream_ids_mask[] = { 0x1fff };
239*91f16700Schasinglulu uint16_t crmu_stream_ids[] = { CRMU_STREAM_ID };
240*91f16700Schasinglulu uint16_t crmu_stream_ids_mask[] = { 0x0 };
241*91f16700Schasinglulu 
242*91f16700Schasinglulu enum arm_smmu_s2cr_type {
243*91f16700Schasinglulu 	S2CR_TYPE_TRANS,
244*91f16700Schasinglulu 	S2CR_TYPE_BYPASS,
245*91f16700Schasinglulu 	S2CR_TYPE_FAULT,
246*91f16700Schasinglulu };
247*91f16700Schasinglulu 
248*91f16700Schasinglulu enum arm_smmu_s2cr_privcfg {
249*91f16700Schasinglulu 	S2CR_PRIVCFG_DEFAULT,
250*91f16700Schasinglulu 	S2CR_PRIVCFG_DIPAN,
251*91f16700Schasinglulu 	S2CR_PRIVCFG_UNPRIV,
252*91f16700Schasinglulu 	S2CR_PRIVCFG_PRIV,
253*91f16700Schasinglulu };
254*91f16700Schasinglulu 
255*91f16700Schasinglulu struct arm_smmu_smr {
256*91f16700Schasinglulu 	uint16_t mask;
257*91f16700Schasinglulu 	uint16_t id;
258*91f16700Schasinglulu 	uint32_t valid;
259*91f16700Schasinglulu };
260*91f16700Schasinglulu 
261*91f16700Schasinglulu struct arm_smmu_s2cr {
262*91f16700Schasinglulu 	int count;
263*91f16700Schasinglulu 	enum arm_smmu_s2cr_type type;
264*91f16700Schasinglulu 	enum arm_smmu_s2cr_privcfg privcfg;
265*91f16700Schasinglulu 	uint8_t cbndx;
266*91f16700Schasinglulu };
267*91f16700Schasinglulu 
268*91f16700Schasinglulu struct arm_smmu_cfg {
269*91f16700Schasinglulu 	uint8_t cbndx;
270*91f16700Schasinglulu 	uint8_t irptndx;
271*91f16700Schasinglulu 	uint32_t cbar;
272*91f16700Schasinglulu };
273*91f16700Schasinglulu 
274*91f16700Schasinglulu struct arm_smmu_device {
275*91f16700Schasinglulu 	uint8_t *base;
276*91f16700Schasinglulu 	uint32_t streams;
277*91f16700Schasinglulu 	unsigned long size;
278*91f16700Schasinglulu 	unsigned long pgshift;
279*91f16700Schasinglulu 	unsigned long va_size;
280*91f16700Schasinglulu 	unsigned long ipa_size;
281*91f16700Schasinglulu 	unsigned long pa_size;
282*91f16700Schasinglulu 	struct arm_smmu_smr smr[NUM_OF_SMRS];
283*91f16700Schasinglulu 	struct arm_smmu_s2cr s2cr[NUM_OF_SMRS];
284*91f16700Schasinglulu 	struct arm_smmu_cfg cfg[NUM_OF_SMRS];
285*91f16700Schasinglulu 	uint16_t *stream_ids;
286*91f16700Schasinglulu 	uint16_t *stream_ids_mask;
287*91f16700Schasinglulu };
288*91f16700Schasinglulu 
289*91f16700Schasinglulu void arm_smmu_enable_secure_client_port(void)
290*91f16700Schasinglulu {
291*91f16700Schasinglulu 	uintptr_t smmu_base = SMMU_BASE;
292*91f16700Schasinglulu 
293*91f16700Schasinglulu 	mmio_clrbits_32(smmu_base, sCR0_CLIENTPD);
294*91f16700Schasinglulu }
295*91f16700Schasinglulu 
296*91f16700Schasinglulu void arm_smmu_reserve_secure_cntxt(void)
297*91f16700Schasinglulu {
298*91f16700Schasinglulu 	uintptr_t smmu_base = SMMU_BASE;
299*91f16700Schasinglulu 
300*91f16700Schasinglulu 	mmio_clrsetbits_32(smmu_base + ARM_SMMU_SMMU_SCR1,
301*91f16700Schasinglulu 			  (SCR1_NSNUMSMRGO_MASK | SCR1_NSNUMCBO_MASK),
302*91f16700Schasinglulu 			  ((ARM_SMMU_NSNUMCBO << SCR1_NSNUMCBO_SHIFT) |
303*91f16700Schasinglulu 			  (ARM_SMMU_NSNUMSMRGO << SCR1_NSNUMSMRGO_SHIFT)));
304*91f16700Schasinglulu }
305*91f16700Schasinglulu 
306*91f16700Schasinglulu static void arm_smmu_smr_cfg(struct arm_smmu_device *smmu, uint32_t index)
307*91f16700Schasinglulu {
308*91f16700Schasinglulu 	uint32_t idx = smmu->cfg[index].cbndx;
309*91f16700Schasinglulu 	struct arm_smmu_smr *smr = &smmu->smr[index];
310*91f16700Schasinglulu 	uint32_t reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT;
311*91f16700Schasinglulu 
312*91f16700Schasinglulu 	if (smr->valid)
313*91f16700Schasinglulu 		reg |= SMR_VALID;
314*91f16700Schasinglulu 
315*91f16700Schasinglulu 	mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) +
316*91f16700Schasinglulu 		      ARM_SMMU_GR0_SMR(idx)), reg);
317*91f16700Schasinglulu }
318*91f16700Schasinglulu 
319*91f16700Schasinglulu static void arm_smmu_s2cr_cfg(struct arm_smmu_device *smmu, uint32_t index)
320*91f16700Schasinglulu {
321*91f16700Schasinglulu 	uint32_t idx = smmu->cfg[index].cbndx;
322*91f16700Schasinglulu 	struct arm_smmu_s2cr *s2cr = &smmu->s2cr[index];
323*91f16700Schasinglulu 
324*91f16700Schasinglulu 	uint32_t reg = (s2cr->type & S2CR_TYPE_MASK) << S2CR_TYPE_SHIFT |
325*91f16700Schasinglulu 		  (s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT |
326*91f16700Schasinglulu 		  (s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT;
327*91f16700Schasinglulu 
328*91f16700Schasinglulu 	mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) +
329*91f16700Schasinglulu 		      ARM_SMMU_GR0_S2CR(idx)), reg);
330*91f16700Schasinglulu }
331*91f16700Schasinglulu 
332*91f16700Schasinglulu static void smmu_set_pgtbl(struct arm_smmu_device *smmu,
333*91f16700Schasinglulu 		    enum iommu_domain dom,
334*91f16700Schasinglulu 		    uint64_t *pg_table_base)
335*91f16700Schasinglulu {
336*91f16700Schasinglulu 	int i, l0_index, l1_index;
337*91f16700Schasinglulu 	uint64_t addr, *pte, *l0_base, *l1_base;
338*91f16700Schasinglulu 	uint64_t addr_space_limit;
339*91f16700Schasinglulu 
340*91f16700Schasinglulu 	if (dom == PCIE_PAXC) {
341*91f16700Schasinglulu 		addr_space_limit = 0xffffffffff;
342*91f16700Schasinglulu 	} else if (dom == DOMAIN_CRMU) {
343*91f16700Schasinglulu 		addr_space_limit = 0xffffffff;
344*91f16700Schasinglulu 	} else {
345*91f16700Schasinglulu 		ERROR("dom is not supported\n");
346*91f16700Schasinglulu 		return;
347*91f16700Schasinglulu 	}
348*91f16700Schasinglulu 
349*91f16700Schasinglulu 	l0_base = pg_table_base;
350*91f16700Schasinglulu 	/* clear L0 descriptors. */
351*91f16700Schasinglulu 	for (i = 0; i < ARM_LPAE_PGTBL_PTE_CNT; i++)
352*91f16700Schasinglulu 		l0_base[i] = 0x0;
353*91f16700Schasinglulu 
354*91f16700Schasinglulu 	addr = 0x0;
355*91f16700Schasinglulu 	while (addr < addr_space_limit) {
356*91f16700Schasinglulu 		/* find L0 pte */
357*91f16700Schasinglulu 		l0_index = ((addr >> ARM_LPAE_PTE_L0_INDEX_SHIFT) &
358*91f16700Schasinglulu 			     ARM_LPAE_PTE_L0_INDEX_MASK);
359*91f16700Schasinglulu 		l1_base = l0_base + ((l0_index + 1) * ARM_LPAE_PGTBL_PTE_CNT);
360*91f16700Schasinglulu 
361*91f16700Schasinglulu 		/* setup L0 pte if required */
362*91f16700Schasinglulu 		pte = l0_base + l0_index;
363*91f16700Schasinglulu 		if (*pte == 0x0) {
364*91f16700Schasinglulu 			*pte |= ((uint64_t)l1_base & ARM_LPAE_PTE_TABLE_MASK);
365*91f16700Schasinglulu 			if (dom == PCIE_PAXC)
366*91f16700Schasinglulu 				*pte |= ARM_LPAE_PTE_NSTABLE;
367*91f16700Schasinglulu 			*pte |= ARM_LPAE_PTE_TABLE;
368*91f16700Schasinglulu 			*pte |= ARM_LPAE_PTE_VALID;
369*91f16700Schasinglulu 		}
370*91f16700Schasinglulu 
371*91f16700Schasinglulu 		/* find L1 pte */
372*91f16700Schasinglulu 		l1_index = ((addr >> ARM_LPAE_PTE_L1_INDEX_SHIFT) &
373*91f16700Schasinglulu 			    ARM_LPAE_PTE_L1_INDEX_MASK);
374*91f16700Schasinglulu 		pte = l1_base + l1_index;
375*91f16700Schasinglulu 
376*91f16700Schasinglulu 		/* setup L1 pte */
377*91f16700Schasinglulu 		*pte = 0x0;
378*91f16700Schasinglulu 		*pte |= (addr & ARM_LPAE_PTE_L1_ADDR_MASK);
379*91f16700Schasinglulu 		if (addr < 0x80000000) {
380*91f16700Schasinglulu 			*pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV <<
381*91f16700Schasinglulu 				 ARM_LPAE_PTE_ATTRINDX);
382*91f16700Schasinglulu 			if (dom == PCIE_PAXC)
383*91f16700Schasinglulu 				*pte |= (1 << ARM_LPAE_PTE_NS);
384*91f16700Schasinglulu 		} else {
385*91f16700Schasinglulu 			*pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE <<
386*91f16700Schasinglulu 				 ARM_LPAE_PTE_ATTRINDX);
387*91f16700Schasinglulu 			*pte |= (1 << ARM_LPAE_PTE_NS);
388*91f16700Schasinglulu 		}
389*91f16700Schasinglulu 		*pte |= (ARM_LPAE_PTE_AP_EL0_RW << ARM_LPAE_PTE_AP);
390*91f16700Schasinglulu 		*pte |= (ARM_LPAE_PTE_SH_INNER << ARM_LPAE_PTE_SH);
391*91f16700Schasinglulu 		*pte |= (1 << ARM_LPAE_PTE_AF);
392*91f16700Schasinglulu 		*pte |= ARM_LPAE_PTE_VALID;
393*91f16700Schasinglulu 
394*91f16700Schasinglulu 		addr += ARM_LPAE_PTE_L1_BLOCK_SIZE;
395*91f16700Schasinglulu 	}
396*91f16700Schasinglulu }
397*91f16700Schasinglulu 
398*91f16700Schasinglulu void arm_smmu_create_identity_map(enum iommu_domain dom)
399*91f16700Schasinglulu {
400*91f16700Schasinglulu 	struct arm_smmu_device iommu;
401*91f16700Schasinglulu 	struct arm_smmu_device *smmu = &iommu;
402*91f16700Schasinglulu 	uint32_t reg, reg2;
403*91f16700Schasinglulu 	unsigned long long reg64;
404*91f16700Schasinglulu 	uint32_t idx;
405*91f16700Schasinglulu 	uint16_t asid;
406*91f16700Schasinglulu 	unsigned int context_bank_index;
407*91f16700Schasinglulu 	unsigned long long pg_table_base;
408*91f16700Schasinglulu 
409*91f16700Schasinglulu 	smmu->base = (uint8_t *) SMMU_BASE;
410*91f16700Schasinglulu 	reg = mmio_read_32((uintptr_t) (ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_ID1));
411*91f16700Schasinglulu 	smmu->pgshift = (reg & ID1_PAGESIZE) ? 16 : 12;
412*91f16700Schasinglulu 	smmu->size = ARM_SMMU_RES_SIZE;
413*91f16700Schasinglulu 	smmu->stream_ids = NULL;
414*91f16700Schasinglulu 
415*91f16700Schasinglulu 	switch (dom) {
416*91f16700Schasinglulu 	case PCIE_PAXC:
417*91f16700Schasinglulu 		smmu->stream_ids = &paxc_stream_ids[0];
418*91f16700Schasinglulu 		smmu->stream_ids_mask = &paxc_stream_ids_mask[0];
419*91f16700Schasinglulu 		smmu->streams = ARRAY_SIZE(paxc_stream_ids);
420*91f16700Schasinglulu 		context_bank_index = SMMU_CTX_BANK_IDX;
421*91f16700Schasinglulu 		pg_table_base = ARM_LPAE_PGTBL_PHYS;
422*91f16700Schasinglulu 		break;
423*91f16700Schasinglulu 	case DOMAIN_CRMU:
424*91f16700Schasinglulu 		smmu->stream_ids = &crmu_stream_ids[0];
425*91f16700Schasinglulu 		smmu->stream_ids_mask = &crmu_stream_ids_mask[0];
426*91f16700Schasinglulu 		smmu->streams = ARRAY_SIZE(crmu_stream_ids);
427*91f16700Schasinglulu 		context_bank_index = SMMU_CTX_BANK_IDX_SECURE_CRMU;
428*91f16700Schasinglulu 		pg_table_base = ARM_LPAE_PGTBL_PHYS_CRMU;
429*91f16700Schasinglulu 		break;
430*91f16700Schasinglulu 	default:
431*91f16700Schasinglulu 		ERROR("domain not supported\n");
432*91f16700Schasinglulu 		return;
433*91f16700Schasinglulu 	}
434*91f16700Schasinglulu 
435*91f16700Schasinglulu 	if (smmu->streams > NUM_OF_SMRS) {
436*91f16700Schasinglulu 		INFO("can not support more than %d sids\n", NUM_OF_SMRS);
437*91f16700Schasinglulu 		return;
438*91f16700Schasinglulu 	}
439*91f16700Schasinglulu 
440*91f16700Schasinglulu 	/* set up iommu dev. */
441*91f16700Schasinglulu 	for (idx = 0; idx < smmu->streams; idx++) {
442*91f16700Schasinglulu 		/* S2CR. */
443*91f16700Schasinglulu 		smmu->s2cr[idx].type = S2CR_TYPE_TRANS;
444*91f16700Schasinglulu 		smmu->s2cr[idx].privcfg = S2CR_PRIVCFG_DEFAULT;
445*91f16700Schasinglulu 		smmu->s2cr[idx].cbndx = context_bank_index;
446*91f16700Schasinglulu 		smmu->cfg[idx].cbndx = context_bank_index;
447*91f16700Schasinglulu 		smmu->cfg[idx].cbar = STG1_WITH_STG2_BYPASS << CBAR_TYPE_SHIFT;
448*91f16700Schasinglulu 		arm_smmu_s2cr_cfg(smmu, idx);
449*91f16700Schasinglulu 
450*91f16700Schasinglulu 		/* SMR. */
451*91f16700Schasinglulu 		smmu->smr[idx].mask = smmu->stream_ids_mask[idx];
452*91f16700Schasinglulu 		smmu->smr[idx].id = smmu->stream_ids[idx];
453*91f16700Schasinglulu 		smmu->smr[idx].valid = 1;
454*91f16700Schasinglulu 		arm_smmu_smr_cfg(smmu, idx);
455*91f16700Schasinglulu 
456*91f16700Schasinglulu 		/* CBA2R. 64-bit Translation */
457*91f16700Schasinglulu 		mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) +
458*91f16700Schasinglulu 			      ARM_SMMU_GR1_CBA2R(smmu->cfg[idx].cbndx)),
459*91f16700Schasinglulu 			      0x1);
460*91f16700Schasinglulu 		/* CBAR.*/
461*91f16700Schasinglulu 		reg = smmu->cfg[idx].cbar;
462*91f16700Schasinglulu 		reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
463*91f16700Schasinglulu 		       (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
464*91f16700Schasinglulu 
465*91f16700Schasinglulu 		mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) +
466*91f16700Schasinglulu 			      ARM_SMMU_GR1_CBAR(smmu->cfg[idx].cbndx)),
467*91f16700Schasinglulu 			      reg);
468*91f16700Schasinglulu 
469*91f16700Schasinglulu 		/* TTBCR. */
470*91f16700Schasinglulu 		reg64 = (ARM_LPAE_TCR_SH_IS << ARM_LPAE_TCR_SH0_SHIFT) |
471*91f16700Schasinglulu 		      (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_IRGN0_SHIFT) |
472*91f16700Schasinglulu 		      (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_ORGN0_SHIFT);
473*91f16700Schasinglulu 		reg64 |= ARM_LPAE_TCR_TG0_4K;
474*91f16700Schasinglulu 		reg64 |= (ARM_LPAE_TCR_PS_40_BIT << ARM_LPAE_TCR_IPS_SHIFT);
475*91f16700Schasinglulu 		/* ias 40 bits.*/
476*91f16700Schasinglulu 		reg64 |= TTBCR_T0SZ(40) << ARM_LPAE_TCR_T0SZ_SHIFT;
477*91f16700Schasinglulu 		/* Disable speculative walks through TTBR1 */
478*91f16700Schasinglulu 		reg64 |= ARM_LPAE_TCR_EPD1;
479*91f16700Schasinglulu 		reg = (uint32_t) reg64;
480*91f16700Schasinglulu 		reg2 = (uint32_t) (reg64 >> 32);
481*91f16700Schasinglulu 		reg2 |= TTBCR2_SEP_UPSTREAM;
482*91f16700Schasinglulu 		reg2 |= TTBCR2_AS;
483*91f16700Schasinglulu 
484*91f16700Schasinglulu 		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
485*91f16700Schasinglulu 			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
486*91f16700Schasinglulu 			      ARM_SMMU_CB_TTBCR2), reg2);
487*91f16700Schasinglulu 
488*91f16700Schasinglulu 		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
489*91f16700Schasinglulu 			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
490*91f16700Schasinglulu 			      ARM_SMMU_CB_TTBCR), reg);
491*91f16700Schasinglulu 
492*91f16700Schasinglulu 		/* TTBR0. */
493*91f16700Schasinglulu 		asid = smmu->cfg[idx].cbndx;
494*91f16700Schasinglulu 		reg64 = pg_table_base;
495*91f16700Schasinglulu 		reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT;
496*91f16700Schasinglulu 
497*91f16700Schasinglulu 		mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
498*91f16700Schasinglulu 			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
499*91f16700Schasinglulu 			      ARM_SMMU_CB_TTBR0), reg64);
500*91f16700Schasinglulu 		/* TTBR1. */
501*91f16700Schasinglulu 		reg64 = 0;
502*91f16700Schasinglulu 		reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT;
503*91f16700Schasinglulu 
504*91f16700Schasinglulu 		mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
505*91f16700Schasinglulu 			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
506*91f16700Schasinglulu 			      ARM_SMMU_CB_TTBR1), reg64);
507*91f16700Schasinglulu 		/* MAIR. */
508*91f16700Schasinglulu 		reg = (ARM_LPAE_MAIR_ATTR_NC
509*91f16700Schasinglulu 			<< ARM_LPAE_MAIR_ATTR_SHIFT
510*91f16700Schasinglulu 			(ARM_LPAE_MAIR_ATTR_IDX_NC)) |
511*91f16700Schasinglulu 			(ARM_LPAE_MAIR_ATTR_WBRWA <<
512*91f16700Schasinglulu 			ARM_LPAE_MAIR_ATTR_SHIFT
513*91f16700Schasinglulu 			(ARM_LPAE_MAIR_ATTR_IDX_CACHE)) |
514*91f16700Schasinglulu 			(ARM_LPAE_MAIR_ATTR_DEVICE <<
515*91f16700Schasinglulu 			ARM_LPAE_MAIR_ATTR_SHIFT
516*91f16700Schasinglulu 			(ARM_LPAE_MAIR_ATTR_IDX_DEV));
517*91f16700Schasinglulu 
518*91f16700Schasinglulu 		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
519*91f16700Schasinglulu 			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
520*91f16700Schasinglulu 			      ARM_SMMU_CB_S1_MAIR0), reg);
521*91f16700Schasinglulu 
522*91f16700Schasinglulu 		/* MAIR1. */
523*91f16700Schasinglulu 		reg = 0;
524*91f16700Schasinglulu 		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
525*91f16700Schasinglulu 			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
526*91f16700Schasinglulu 			      ARM_SMMU_CB_S1_MAIR1), reg);
527*91f16700Schasinglulu 		/* SCTLR. */
528*91f16700Schasinglulu 		reg = SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE | SCTLR_M;
529*91f16700Schasinglulu 		/* stage 1.*/
530*91f16700Schasinglulu 		reg |= SCTLR_S1_ASIDPNE;
531*91f16700Schasinglulu 		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
532*91f16700Schasinglulu 			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
533*91f16700Schasinglulu 			      ARM_SMMU_CB_SCTLR), reg);
534*91f16700Schasinglulu 	}
535*91f16700Schasinglulu 	smmu_set_pgtbl(smmu, dom, (uint64_t *)pg_table_base);
536*91f16700Schasinglulu }
537