blob: 789f11c8d8d917c37306025d3e5e2367a5b6892c [file] [log] [blame]
Varun Wadekar3c959932016-03-03 13:09:08 -08001/*
Antonio Nino Diaz4b32e622018-08-16 16:52:57 +01002 * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
Varun Wadekar3c959932016-03-03 13:09:08 -08003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Varun Wadekar3c959932016-03-03 13:09:08 -08005 */
6
7#include <assert.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008#include <string.h>
9
Varun Wadekar93bed2a2016-03-18 13:07:33 -070010#include <platform_def.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011
12#include <common/bl_common.h>
13#include <common/debug.h>
14
Varun Wadekar3c959932016-03-03 13:09:08 -080015#include <smmu.h>
Varun Wadekar93bed2a2016-03-18 13:07:33 -070016#include <tegra_private.h>
Varun Wadekar3c959932016-03-03 13:09:08 -080017
Antonio Nino Diaz4b32e622018-08-16 16:52:57 +010018extern void memcpy16(void *dest, const void *src, unsigned int length);
19
Pritesh Raithatha0de6e532017-01-24 13:49:46 +053020/* SMMU IDs currently supported by the driver */
21enum {
Anthony Zhou0e07e452017-07-26 17:16:54 +080022 TEGRA_SMMU0 = 0U,
Pritesh Raithatha0de6e532017-01-24 13:49:46 +053023 TEGRA_SMMU1,
24 TEGRA_SMMU2
25};
26
27static uint32_t tegra_smmu_read_32(uint32_t smmu_id, uint32_t off)
28{
Anthony Zhou0844b972017-06-28 16:35:54 +080029 uint32_t ret = 0U;
30
Pritesh Raithatha0de6e532017-01-24 13:49:46 +053031#if defined(TEGRA_SMMU0_BASE)
Anthony Zhou0844b972017-06-28 16:35:54 +080032 if (smmu_id == TEGRA_SMMU0) {
33 ret = mmio_read_32(TEGRA_SMMU0_BASE + (uint64_t)off);
34 }
Pritesh Raithatha0de6e532017-01-24 13:49:46 +053035#endif
36
37#if defined(TEGRA_SMMU1_BASE)
Anthony Zhou0844b972017-06-28 16:35:54 +080038 if (smmu_id == TEGRA_SMMU1) {
39 ret = mmio_read_32(TEGRA_SMMU1_BASE + (uint64_t)off);
40 }
Pritesh Raithatha0de6e532017-01-24 13:49:46 +053041#endif
42
43#if defined(TEGRA_SMMU2_BASE)
Anthony Zhou0844b972017-06-28 16:35:54 +080044 if (smmu_id == TEGRA_SMMU2) {
45 ret = mmio_read_32(TEGRA_SMMU2_BASE + (uint64_t)off);
46 }
Pritesh Raithatha0de6e532017-01-24 13:49:46 +053047#endif
48
Anthony Zhou0844b972017-06-28 16:35:54 +080049 return ret;
Pritesh Raithatha0de6e532017-01-24 13:49:46 +053050}
51
52static void tegra_smmu_write_32(uint32_t smmu_id,
53 uint32_t off, uint32_t val)
54{
55#if defined(TEGRA_SMMU0_BASE)
Anthony Zhou0844b972017-06-28 16:35:54 +080056 if (smmu_id == TEGRA_SMMU0) {
57 mmio_write_32(TEGRA_SMMU0_BASE + (uint64_t)off, val);
58 }
Pritesh Raithatha0de6e532017-01-24 13:49:46 +053059#endif
60
61#if defined(TEGRA_SMMU1_BASE)
Anthony Zhou0844b972017-06-28 16:35:54 +080062 if (smmu_id == TEGRA_SMMU1) {
63 mmio_write_32(TEGRA_SMMU1_BASE + (uint64_t)off, val);
64 }
Pritesh Raithatha0de6e532017-01-24 13:49:46 +053065#endif
66
67#if defined(TEGRA_SMMU2_BASE)
Anthony Zhou0844b972017-06-28 16:35:54 +080068 if (smmu_id == TEGRA_SMMU2) {
69 mmio_write_32(TEGRA_SMMU2_BASE + (uint64_t)off, val);
70 }
Pritesh Raithatha0de6e532017-01-24 13:49:46 +053071#endif
72}
73
Varun Wadekar3c959932016-03-03 13:09:08 -080074/*
Varun Wadekar93bed2a2016-03-18 13:07:33 -070075 * Save SMMU settings before "System Suspend" to TZDRAM
Varun Wadekar3c959932016-03-03 13:09:08 -080076 */
Varun Wadekar93bed2a2016-03-18 13:07:33 -070077void tegra_smmu_save_context(uint64_t smmu_ctx_addr)
Varun Wadekar3c959932016-03-03 13:09:08 -080078{
Varun Wadekar27155fc2017-04-20 18:56:09 -070079 uint32_t i, num_entries = 0;
Pritesh Raithathac88654f2017-01-02 20:11:32 +053080 smmu_regs_t *smmu_ctx_regs;
Anthony Zhou0844b972017-06-28 16:35:54 +080081 const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
Varun Wadekar93bed2a2016-03-18 13:07:33 -070082 uint64_t tzdram_base = params_from_bl2->tzdram_base;
83 uint64_t tzdram_end = tzdram_base + params_from_bl2->tzdram_size;
Varun Wadekar3c959932016-03-03 13:09:08 -080084 uint32_t reg_id1, pgshift, cb_size;
85
86 /* sanity check SMMU settings c*/
Pritesh Raithatha0de6e532017-01-24 13:49:46 +053087 reg_id1 = mmio_read_32((TEGRA_SMMU0_BASE + SMMU_GNSR0_IDR1));
Anthony Zhou0844b972017-06-28 16:35:54 +080088 pgshift = ((reg_id1 & ID1_PAGESIZE) != 0U) ? 16U : 12U;
Anthony Zhou0e07e452017-07-26 17:16:54 +080089 cb_size = ((uint32_t)2 << pgshift) * \
90 ((uint32_t)1 << (((reg_id1 >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1U));
Varun Wadekar3c959932016-03-03 13:09:08 -080091
92 assert(!((pgshift != PGSHIFT) || (cb_size != CB_SIZE)));
Varun Wadekar93bed2a2016-03-18 13:07:33 -070093 assert((smmu_ctx_addr >= tzdram_base) && (smmu_ctx_addr <= tzdram_end));
94
Pritesh Raithathac88654f2017-01-02 20:11:32 +053095 /* get SMMU context table */
96 smmu_ctx_regs = plat_get_smmu_ctx();
Anthony Zhou4408e882017-07-07 14:29:51 +080097 assert(smmu_ctx_regs != NULL);
Varun Wadekar3c959932016-03-03 13:09:08 -080098
Varun Wadekar27155fc2017-04-20 18:56:09 -070099 /*
100 * smmu_ctx_regs[0].val contains the size of the context table minus
101 * the last entry. Sanity check the table size before we start with
102 * the context save operation.
103 */
104 while (smmu_ctx_regs[num_entries].val != 0xFFFFFFFFU) {
105 num_entries++;
106 }
107
108 /* panic if the sizes do not match */
Anthony Zhou0844b972017-06-28 16:35:54 +0800109 if (num_entries != smmu_ctx_regs[0].val) {
Varun Wadekar27155fc2017-04-20 18:56:09 -0700110 panic();
Anthony Zhou0844b972017-06-28 16:35:54 +0800111 }
Varun Wadekar27155fc2017-04-20 18:56:09 -0700112
Varun Wadekar3c959932016-03-03 13:09:08 -0800113 /* save SMMU register values */
Anthony Zhou0e07e452017-07-26 17:16:54 +0800114 for (i = 1U; i < num_entries; i++) {
Varun Wadekar3c959932016-03-03 13:09:08 -0800115 smmu_ctx_regs[i].val = mmio_read_32(smmu_ctx_regs[i].reg);
Anthony Zhou0e07e452017-07-26 17:16:54 +0800116 }
Varun Wadekar3c959932016-03-03 13:09:08 -0800117
Varun Wadekar27155fc2017-04-20 18:56:09 -0700118 /* increment by 1 to take care of the last entry */
119 num_entries++;
120
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700121 /* Save SMMU config settings */
Anthony Zhou0844b972017-06-28 16:35:54 +0800122 (void)memcpy16((uint8_t *)smmu_ctx_addr, (uint8_t *)smmu_ctx_regs,
123 (sizeof(smmu_regs_t) * num_entries));
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700124
Varun Wadekar3c959932016-03-03 13:09:08 -0800125 /* save the SMMU table address */
126 mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV11_LO,
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700127 (uint32_t)smmu_ctx_addr);
Varun Wadekar3c959932016-03-03 13:09:08 -0800128 mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV11_HI,
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700129 (uint32_t)(smmu_ctx_addr >> 32));
Varun Wadekar3c959932016-03-03 13:09:08 -0800130}
131
Varun Wadekarea709c32016-04-20 17:14:15 -0700132#define SMMU_NUM_CONTEXTS 64
133#define SMMU_CONTEXT_BANK_MAX_IDX 64
134
Varun Wadekar3c959932016-03-03 13:09:08 -0800135/*
136 * Init SMMU during boot or "System Suspend" exit
137 */
138void tegra_smmu_init(void)
139{
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530140 uint32_t val, cb_idx, smmu_id, ctx_base;
Steven Kao7fd30f52017-07-25 11:29:46 +0800141 uint32_t smmu_counter = plat_get_num_smmu_devices();
142
Anthony Zhou0e07e452017-07-26 17:16:54 +0800143 for (smmu_id = 0U; smmu_id < smmu_counter; smmu_id++) {
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530144 /* Program the SMMU pagesize and reset CACHE_LOCK bit */
145 val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
146 val |= SMMU_GSR0_PGSIZE_64K;
Anthony Zhou0e07e452017-07-26 17:16:54 +0800147 val &= (uint32_t)~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530148 tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val);
Varun Wadekarea709c32016-04-20 17:14:15 -0700149
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530150 /* reset CACHE LOCK bit for NS Aux. Config. Register */
151 val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR);
Anthony Zhou0e07e452017-07-26 17:16:54 +0800152 val &= (uint32_t)~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530153 tegra_smmu_write_32(smmu_id, SMMU_GNSR_ACR, val);
Varun Wadekarea709c32016-04-20 17:14:15 -0700154
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530155 /* disable TCU prefetch for all contexts */
156 ctx_base = (SMMU_GSR0_PGSIZE_64K * SMMU_NUM_CONTEXTS)
157 + SMMU_CBn_ACTLR;
158 for (cb_idx = 0; cb_idx < SMMU_CONTEXT_BANK_MAX_IDX; cb_idx++) {
159 val = tegra_smmu_read_32(smmu_id,
160 ctx_base + (SMMU_GSR0_PGSIZE_64K * cb_idx));
Anthony Zhou0e07e452017-07-26 17:16:54 +0800161 val &= (uint32_t)~SMMU_CBn_ACTLR_CPRE_BIT;
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530162 tegra_smmu_write_32(smmu_id, ctx_base +
163 (SMMU_GSR0_PGSIZE_64K * cb_idx), val);
164 }
Varun Wadekarea709c32016-04-20 17:14:15 -0700165
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530166 /* set CACHE LOCK bit for NS Aux. Config. Register */
167 val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR);
Anthony Zhou0e07e452017-07-26 17:16:54 +0800168 val |= (uint32_t)SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530169 tegra_smmu_write_32(smmu_id, SMMU_GNSR_ACR, val);
Varun Wadekarea709c32016-04-20 17:14:15 -0700170
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530171 /* set CACHE LOCK bit for S Aux. Config. Register */
172 val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
Anthony Zhou0e07e452017-07-26 17:16:54 +0800173 val |= (uint32_t)SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530174 tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val);
175 }
Varun Wadekar3c959932016-03-03 13:09:08 -0800176}