blob: bff95d7ce2e7321aa6fe4b1d4111a69885c676ac [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 {
22 TEGRA_SMMU0,
23 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;
89 cb_size = (2UL << pgshift) * \
90 (1UL << (((reg_id1 >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1UL));
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();
97 assert(smmu_ctx_regs);
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 */
Varun Wadekar27155fc2017-04-20 18:56:09 -0700114 for (i = 1; 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);
116
Varun Wadekar27155fc2017-04-20 18:56:09 -0700117 /* increment by 1 to take care of the last entry */
118 num_entries++;
119
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700120 /* Save SMMU config settings */
Anthony Zhou0844b972017-06-28 16:35:54 +0800121 (void)memcpy16((uint8_t *)smmu_ctx_addr, (uint8_t *)smmu_ctx_regs,
122 (sizeof(smmu_regs_t) * num_entries));
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700123
Varun Wadekar3c959932016-03-03 13:09:08 -0800124 /* save the SMMU table address */
125 mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV11_LO,
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700126 (uint32_t)smmu_ctx_addr);
Varun Wadekar3c959932016-03-03 13:09:08 -0800127 mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV11_HI,
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700128 (uint32_t)(smmu_ctx_addr >> 32));
Varun Wadekar3c959932016-03-03 13:09:08 -0800129}
130
Varun Wadekarea709c32016-04-20 17:14:15 -0700131#define SMMU_NUM_CONTEXTS 64
132#define SMMU_CONTEXT_BANK_MAX_IDX 64
133
Varun Wadekar3c959932016-03-03 13:09:08 -0800134/*
135 * Init SMMU during boot or "System Suspend" exit
136 */
137void tegra_smmu_init(void)
138{
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530139 uint32_t val, cb_idx, smmu_id, ctx_base;
Varun Wadekar3c959932016-03-03 13:09:08 -0800140
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530141 for (smmu_id = 0; smmu_id < NUM_SMMU_DEVICES; smmu_id++) {
142 /* Program the SMMU pagesize and reset CACHE_LOCK bit */
143 val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
144 val |= SMMU_GSR0_PGSIZE_64K;
145 val &= ~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
146 tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val);
Varun Wadekarea709c32016-04-20 17:14:15 -0700147
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530148 /* reset CACHE LOCK bit for NS Aux. Config. Register */
149 val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR);
150 val &= ~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
151 tegra_smmu_write_32(smmu_id, SMMU_GNSR_ACR, val);
Varun Wadekarea709c32016-04-20 17:14:15 -0700152
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530153 /* disable TCU prefetch for all contexts */
154 ctx_base = (SMMU_GSR0_PGSIZE_64K * SMMU_NUM_CONTEXTS)
155 + SMMU_CBn_ACTLR;
156 for (cb_idx = 0; cb_idx < SMMU_CONTEXT_BANK_MAX_IDX; cb_idx++) {
157 val = tegra_smmu_read_32(smmu_id,
158 ctx_base + (SMMU_GSR0_PGSIZE_64K * cb_idx));
159 val &= ~SMMU_CBn_ACTLR_CPRE_BIT;
160 tegra_smmu_write_32(smmu_id, ctx_base +
161 (SMMU_GSR0_PGSIZE_64K * cb_idx), val);
162 }
Varun Wadekarea709c32016-04-20 17:14:15 -0700163
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530164 /* set CACHE LOCK bit for NS Aux. Config. Register */
165 val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR);
166 val |= SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
167 tegra_smmu_write_32(smmu_id, SMMU_GNSR_ACR, val);
Varun Wadekarea709c32016-04-20 17:14:15 -0700168
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530169 /* set CACHE LOCK bit for S Aux. Config. Register */
170 val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
171 val |= SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
172 tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val);
173 }
Varun Wadekar3c959932016-03-03 13:09:08 -0800174}