xref: /aosp_15_r20/external/arm-trusted-firmware/drivers/arm/smmu/smmu_v3.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #include <common/debug.h>
8*54fd6939SJiyong Park #include <cdefs.h>
9*54fd6939SJiyong Park #include <drivers/arm/smmu_v3.h>
10*54fd6939SJiyong Park #include <drivers/delay_timer.h>
11*54fd6939SJiyong Park #include <lib/mmio.h>
12*54fd6939SJiyong Park 
13*54fd6939SJiyong Park /* SMMU poll number of retries */
14*54fd6939SJiyong Park #define SMMU_POLL_TIMEOUT_US	U(1000)
15*54fd6939SJiyong Park 
smmuv3_poll(uintptr_t smmu_reg,uint32_t mask,uint32_t value)16*54fd6939SJiyong Park static int __init smmuv3_poll(uintptr_t smmu_reg, uint32_t mask,
17*54fd6939SJiyong Park 				uint32_t value)
18*54fd6939SJiyong Park {
19*54fd6939SJiyong Park 	uint32_t reg_val;
20*54fd6939SJiyong Park 	uint64_t timeout;
21*54fd6939SJiyong Park 
22*54fd6939SJiyong Park 	/* Set 1ms timeout value */
23*54fd6939SJiyong Park 	timeout = timeout_init_us(SMMU_POLL_TIMEOUT_US);
24*54fd6939SJiyong Park 	do {
25*54fd6939SJiyong Park 		reg_val = mmio_read_32(smmu_reg);
26*54fd6939SJiyong Park 		if ((reg_val & mask) == value)
27*54fd6939SJiyong Park 			return 0;
28*54fd6939SJiyong Park 	} while (!timeout_elapsed(timeout));
29*54fd6939SJiyong Park 
30*54fd6939SJiyong Park 	ERROR("Timeout polling SMMUv3 register @%p\n", (void *)smmu_reg);
31*54fd6939SJiyong Park 	ERROR("Read value 0x%x, expected 0x%x\n", reg_val,
32*54fd6939SJiyong Park 		value == 0U ? reg_val & ~mask : reg_val | mask);
33*54fd6939SJiyong Park 	return -1;
34*54fd6939SJiyong Park }
35*54fd6939SJiyong Park 
36*54fd6939SJiyong Park /*
37*54fd6939SJiyong Park  * Abort all incoming transactions in order to implement a default
38*54fd6939SJiyong Park  * deny policy on reset.
39*54fd6939SJiyong Park  */
smmuv3_security_init(uintptr_t smmu_base)40*54fd6939SJiyong Park int __init smmuv3_security_init(uintptr_t smmu_base)
41*54fd6939SJiyong Park {
42*54fd6939SJiyong Park 	/* Attribute update has completed when SMMU_(S)_GBPA.Update bit is 0 */
43*54fd6939SJiyong Park 	if (smmuv3_poll(smmu_base + SMMU_GBPA, SMMU_GBPA_UPDATE, 0U) != 0U)
44*54fd6939SJiyong Park 		return -1;
45*54fd6939SJiyong Park 
46*54fd6939SJiyong Park 	/*
47*54fd6939SJiyong Park 	 * SMMU_(S)_CR0 resets to zero with all streams bypassing the SMMU,
48*54fd6939SJiyong Park 	 * so just abort all incoming transactions.
49*54fd6939SJiyong Park 	 */
50*54fd6939SJiyong Park 	mmio_setbits_32(smmu_base + SMMU_GBPA,
51*54fd6939SJiyong Park 			SMMU_GBPA_UPDATE | SMMU_GBPA_ABORT);
52*54fd6939SJiyong Park 
53*54fd6939SJiyong Park 	if (smmuv3_poll(smmu_base + SMMU_GBPA, SMMU_GBPA_UPDATE, 0U) != 0U)
54*54fd6939SJiyong Park 		return -1;
55*54fd6939SJiyong Park 
56*54fd6939SJiyong Park 	/* Check if the SMMU supports secure state */
57*54fd6939SJiyong Park 	if ((mmio_read_32(smmu_base + SMMU_S_IDR1) &
58*54fd6939SJiyong Park 				SMMU_S_IDR1_SECURE_IMPL) == 0U)
59*54fd6939SJiyong Park 		return 0;
60*54fd6939SJiyong Park 
61*54fd6939SJiyong Park 	/* Abort all incoming secure transactions */
62*54fd6939SJiyong Park 	if (smmuv3_poll(smmu_base + SMMU_S_GBPA, SMMU_S_GBPA_UPDATE, 0U) != 0U)
63*54fd6939SJiyong Park 		return -1;
64*54fd6939SJiyong Park 
65*54fd6939SJiyong Park 	mmio_setbits_32(smmu_base + SMMU_S_GBPA,
66*54fd6939SJiyong Park 			SMMU_S_GBPA_UPDATE | SMMU_S_GBPA_ABORT);
67*54fd6939SJiyong Park 
68*54fd6939SJiyong Park 	return smmuv3_poll(smmu_base + SMMU_S_GBPA, SMMU_S_GBPA_UPDATE, 0U);
69*54fd6939SJiyong Park }
70*54fd6939SJiyong Park 
71*54fd6939SJiyong Park /*
72*54fd6939SJiyong Park  * Initialize the SMMU by invalidating all secure caches and TLBs.
73*54fd6939SJiyong Park  * Abort all incoming transactions in order to implement a default
74*54fd6939SJiyong Park  * deny policy on reset
75*54fd6939SJiyong Park  */
smmuv3_init(uintptr_t smmu_base)76*54fd6939SJiyong Park int __init smmuv3_init(uintptr_t smmu_base)
77*54fd6939SJiyong Park {
78*54fd6939SJiyong Park 	/* Abort all incoming transactions */
79*54fd6939SJiyong Park 	if (smmuv3_security_init(smmu_base) != 0)
80*54fd6939SJiyong Park 		return -1;
81*54fd6939SJiyong Park 
82*54fd6939SJiyong Park 	/* Check if the SMMU supports secure state */
83*54fd6939SJiyong Park 	if ((mmio_read_32(smmu_base + SMMU_S_IDR1) &
84*54fd6939SJiyong Park 				SMMU_S_IDR1_SECURE_IMPL) == 0U)
85*54fd6939SJiyong Park 		return 0;
86*54fd6939SJiyong Park 	/*
87*54fd6939SJiyong Park 	 * Initiate invalidation of secure caches and TLBs if the SMMU
88*54fd6939SJiyong Park 	 * supports secure state. If not, it's implementation defined
89*54fd6939SJiyong Park 	 * as to how SMMU_S_INIT register is accessed.
90*54fd6939SJiyong Park 	 */
91*54fd6939SJiyong Park 	mmio_write_32(smmu_base + SMMU_S_INIT, SMMU_S_INIT_INV_ALL);
92*54fd6939SJiyong Park 
93*54fd6939SJiyong Park 	/* Wait for global invalidation operation to finish */
94*54fd6939SJiyong Park 	return smmuv3_poll(smmu_base + SMMU_S_INIT,
95*54fd6939SJiyong Park 				SMMU_S_INIT_INV_ALL, 0U);
96*54fd6939SJiyong Park }
97