blob: 8c1b899f77ed4ba66cb8a1e956d0590d3929038b [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 */
Varun Wadekar4ede3a62017-11-08 14:03:16 -0800104 while ((smmu_ctx_regs[num_entries].reg != 0xFFFFFFFFU)) {
Varun Wadekar27155fc2017-04-20 18:56:09 -0700105 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 Wadekar4ede3a62017-11-08 14:03:16 -0800110 ERROR("SMMU context size mismatch!");
Varun Wadekar27155fc2017-04-20 18:56:09 -0700111 panic();
Anthony Zhou0844b972017-06-28 16:35:54 +0800112 }
Varun Wadekar27155fc2017-04-20 18:56:09 -0700113
Varun Wadekar3c959932016-03-03 13:09:08 -0800114 /* save SMMU register values */
Anthony Zhou0e07e452017-07-26 17:16:54 +0800115 for (i = 1U; i < num_entries; i++) {
Varun Wadekar3c959932016-03-03 13:09:08 -0800116 smmu_ctx_regs[i].val = mmio_read_32(smmu_ctx_regs[i].reg);
Anthony Zhou0e07e452017-07-26 17:16:54 +0800117 }
Varun Wadekar3c959932016-03-03 13:09:08 -0800118
Varun Wadekar27155fc2017-04-20 18:56:09 -0700119 /* increment by 1 to take care of the last entry */
120 num_entries++;
121
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700122 /* Save SMMU config settings */
Anthony Zhou0844b972017-06-28 16:35:54 +0800123 (void)memcpy16((uint8_t *)smmu_ctx_addr, (uint8_t *)smmu_ctx_regs,
124 (sizeof(smmu_regs_t) * num_entries));
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700125
Varun Wadekar3c959932016-03-03 13:09:08 -0800126 /* save the SMMU table address */
Steven Kao186485e2017-10-23 18:22:09 +0800127 mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SMMU_TABLE_ADDR_LO,
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700128 (uint32_t)smmu_ctx_addr);
Steven Kao186485e2017-10-23 18:22:09 +0800129 mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SMMU_TABLE_ADDR_HI,
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700130 (uint32_t)(smmu_ctx_addr >> 32));
Varun Wadekar3c959932016-03-03 13:09:08 -0800131}
132
Varun Wadekarea709c32016-04-20 17:14:15 -0700133#define SMMU_NUM_CONTEXTS 64
134#define SMMU_CONTEXT_BANK_MAX_IDX 64
135
Varun Wadekar3c959932016-03-03 13:09:08 -0800136/*
137 * Init SMMU during boot or "System Suspend" exit
138 */
139void tegra_smmu_init(void)
140{
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530141 uint32_t val, cb_idx, smmu_id, ctx_base;
Steven Kao7fd30f52017-07-25 11:29:46 +0800142 uint32_t smmu_counter = plat_get_num_smmu_devices();
143
Anthony Zhou0e07e452017-07-26 17:16:54 +0800144 for (smmu_id = 0U; smmu_id < smmu_counter; smmu_id++) {
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530145 /* Program the SMMU pagesize and reset CACHE_LOCK bit */
146 val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
147 val |= SMMU_GSR0_PGSIZE_64K;
Anthony Zhou0e07e452017-07-26 17:16:54 +0800148 val &= (uint32_t)~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530149 tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val);
Varun Wadekarea709c32016-04-20 17:14:15 -0700150
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530151 /* reset CACHE LOCK bit for NS Aux. Config. Register */
152 val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR);
Anthony Zhou0e07e452017-07-26 17:16:54 +0800153 val &= (uint32_t)~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530154 tegra_smmu_write_32(smmu_id, SMMU_GNSR_ACR, val);
Varun Wadekarea709c32016-04-20 17:14:15 -0700155
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530156 /* disable TCU prefetch for all contexts */
157 ctx_base = (SMMU_GSR0_PGSIZE_64K * SMMU_NUM_CONTEXTS)
158 + SMMU_CBn_ACTLR;
159 for (cb_idx = 0; cb_idx < SMMU_CONTEXT_BANK_MAX_IDX; cb_idx++) {
160 val = tegra_smmu_read_32(smmu_id,
161 ctx_base + (SMMU_GSR0_PGSIZE_64K * cb_idx));
Anthony Zhou0e07e452017-07-26 17:16:54 +0800162 val &= (uint32_t)~SMMU_CBn_ACTLR_CPRE_BIT;
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530163 tegra_smmu_write_32(smmu_id, ctx_base +
164 (SMMU_GSR0_PGSIZE_64K * cb_idx), val);
165 }
Varun Wadekarea709c32016-04-20 17:14:15 -0700166
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530167 /* set CACHE LOCK bit for NS Aux. Config. Register */
168 val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR);
Anthony Zhou0e07e452017-07-26 17:16:54 +0800169 val |= (uint32_t)SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530170 tegra_smmu_write_32(smmu_id, SMMU_GNSR_ACR, val);
Varun Wadekarea709c32016-04-20 17:14:15 -0700171
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530172 /* set CACHE LOCK bit for S Aux. Config. Register */
173 val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
Anthony Zhou0e07e452017-07-26 17:16:54 +0800174 val |= (uint32_t)SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
Pritesh Raithatha0de6e532017-01-24 13:49:46 +0530175 tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val);
176 }
Varun Wadekar3c959932016-03-03 13:09:08 -0800177}