blob: 5493b850a920a2e1677fa3df1cb7cc3dcb290518 [file] [log] [blame]
Jeenu Viswambharan5c503042017-05-26 14:15:40 +01001/*
Alexei Fedorov6b4a5f02019-04-26 12:07:07 +01002 * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
Jeenu Viswambharan5c503042017-05-26 14:15:40 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Alexei Fedorov6b4a5f02019-04-26 12:07:07 +01007#include <common/debug.h>
Daniel Boulby844b4872018-09-18 13:36:39 +01008#include <cdefs.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00009#include <drivers/arm/smmu_v3.h>
10#include <lib/mmio.h>
11
Alexei Fedorov6b4a5f02019-04-26 12:07:07 +010012/* SMMU poll number of retries */
13#define SMMU_POLL_RETRY 1000000
Jeenu Viswambharan5c503042017-05-26 14:15:40 +010014
Alexei Fedorov6b4a5f02019-04-26 12:07:07 +010015static int __init smmuv3_poll(uintptr_t smmu_reg, uint32_t mask,
16 uint32_t value)
Jeenu Viswambharan5c503042017-05-26 14:15:40 +010017{
Alexei Fedorov6b4a5f02019-04-26 12:07:07 +010018 uint32_t reg_val, retries = SMMU_POLL_RETRY;
Jeenu Viswambharan5c503042017-05-26 14:15:40 +010019
Alexei Fedorov6b4a5f02019-04-26 12:07:07 +010020 do {
21 reg_val = mmio_read_32(smmu_reg);
22 if ((reg_val & mask) == value)
23 return 0;
24 } while (--retries != 0U);
Jeenu Viswambharan5c503042017-05-26 14:15:40 +010025
Alexei Fedorov6b4a5f02019-04-26 12:07:07 +010026 ERROR("Failed to poll SMMUv3 register @%p\n", (void *)smmu_reg);
27 ERROR("Read value 0x%x, expected 0x%x\n", reg_val,
28 value == 0U ? reg_val & ~mask : reg_val | mask);
29 return -1;
Antonio Nino Diazfeacba32018-08-21 16:12:29 +010030}
31
Jeenu Viswambharan5c503042017-05-26 14:15:40 +010032/*
Alexei Fedorov896799a2019-05-09 12:14:40 +010033 * Abort all incoming transactions in order to implement a default
34 * deny policy on reset.
35 */
36int __init smmuv3_security_init(uintptr_t smmu_base)
37{
38 /* Attribute update has completed when SMMU_(S)_GBPA.Update bit is 0 */
39 if (smmuv3_poll(smmu_base + SMMU_GBPA, SMMU_GBPA_UPDATE, 0U) != 0U)
40 return -1;
41
42 /*
43 * SMMU_(S)_CR0 resets to zero with all streams bypassing the SMMU,
44 * so just abort all incoming transactions.
45 */
46 mmio_setbits_32(smmu_base + SMMU_GBPA,
47 SMMU_GBPA_UPDATE | SMMU_GBPA_ABORT);
48
49 if (smmuv3_poll(smmu_base + SMMU_GBPA, SMMU_GBPA_UPDATE, 0U) != 0U)
50 return -1;
51
52 /* Check if the SMMU supports secure state */
53 if ((mmio_read_32(smmu_base + SMMU_S_IDR1) &
54 SMMU_S_IDR1_SECURE_IMPL) == 0U)
55 return 0;
56
57 /* Abort all incoming secure transactions */
58 if (smmuv3_poll(smmu_base + SMMU_S_GBPA, SMMU_S_GBPA_UPDATE, 0U) != 0U)
59 return -1;
60
61 mmio_setbits_32(smmu_base + SMMU_S_GBPA,
62 SMMU_S_GBPA_UPDATE | SMMU_S_GBPA_ABORT);
63
64 return smmuv3_poll(smmu_base + SMMU_S_GBPA, SMMU_S_GBPA_UPDATE, 0U);
65}
66
67/*
Jeenu Viswambharan5c503042017-05-26 14:15:40 +010068 * Initialize the SMMU by invalidating all secure caches and TLBs.
Alexei Fedorov6b4a5f02019-04-26 12:07:07 +010069 * Abort all incoming transactions in order to implement a default
70 * deny policy on reset
Jeenu Viswambharan5c503042017-05-26 14:15:40 +010071 */
Daniel Boulby844b4872018-09-18 13:36:39 +010072int __init smmuv3_init(uintptr_t smmu_base)
Jeenu Viswambharan5c503042017-05-26 14:15:40 +010073{
Alexei Fedorov896799a2019-05-09 12:14:40 +010074 /* Abort all incoming transactions */
75 if (smmuv3_security_init(smmu_base) != 0)
76 return -1;
77
78 /* Check if the SMMU supports secure state */
79 if ((mmio_read_32(smmu_base + SMMU_S_IDR1) &
80 SMMU_S_IDR1_SECURE_IMPL) == 0U)
81 return 0;
Jeenu Viswambharan5c503042017-05-26 14:15:40 +010082 /*
Alexei Fedorov896799a2019-05-09 12:14:40 +010083 * Initiate invalidation of secure caches and TLBs if the SMMU
84 * supports secure state. If not, it's implementation defined
85 * as to how SMMU_S_INIT register is accessed.
Jeenu Viswambharan5c503042017-05-26 14:15:40 +010086 */
Alexei Fedorov896799a2019-05-09 12:14:40 +010087 mmio_write_32(smmu_base + SMMU_S_INIT, SMMU_S_INIT_INV_ALL);
Jeenu Viswambharan5c503042017-05-26 14:15:40 +010088
Alexei Fedorov896799a2019-05-09 12:14:40 +010089 /* Wait for global invalidation operation to finish */
90 return smmuv3_poll(smmu_base + SMMU_S_INIT,
91 SMMU_S_INIT_INV_ALL, 0U);
Jeenu Viswambharan5c503042017-05-26 14:15:40 +010092}