1 /*
2 * Copyright (c) 2023 - 2024, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <helpers/nrfx_ram_ctrl.h>
35
36 typedef struct
37 {
38 uint8_t block:4;
39 uint8_t section:4;
40 } ram_block_section_t;
41
42 typedef union
43 {
44 ram_block_section_t decoded;
45 uint8_t raw;
46 } ram_unit_t;
47
48 #if !defined(NRF_MEMORY_RAM_BASE) && defined(NRF_MEMORY_RAM0_BASE)
49 #define NRF_MEMORY_RAM_BASE NRF_MEMORY_RAM0_BASE
50 #endif
51
52 #define RAM_NON_UNIFORM_SECTION_DECLARE(i, _block, _section) {.decoded = {_block, _section}}
53
54 #if defined(NRF51)
55 #define RAM_SECTION_UNIT_SIZE 8192
56 #define RAM_UNIFORM_BLOCKS 4
57 #define RAM_UNIFORM_SECTIONS_PER_BLOCK 1
58 #define RAM_UNIFORM_SECTIONS_TOTAL 4
59 #error "Unsupported device."
60 #elif defined(NRF52805_XXAA) || defined(NRF52810_XXAA) || defined(NRF52811_XXAA)
61 #define RAM_SECTION_UNIT_SIZE 4096
62 #define RAM_UNIFORM_BLOCKS 3
63 #define RAM_UNIFORM_SECTIONS_PER_BLOCK 2
64 #define RAM_UNIFORM_SECTIONS_TOTAL 6
65 #elif defined(NRF52820_XXAA)
66 #define RAM_SECTION_UNIT_SIZE 4096
67 #define RAM_UNIFORM_BLOCKS 4
68 #define RAM_UNIFORM_SECTIONS_PER_BLOCK 2
69 #define RAM_UNIFORM_SECTIONS_TOTAL 8
70 #elif defined(NRF52832_XXAA)
71 #define RAM_SECTION_UNIT_SIZE 4096
72 #define RAM_UNIFORM_BLOCKS 8
73 #define RAM_UNIFORM_SECTIONS_PER_BLOCK 2
74 #define RAM_UNIFORM_SECTIONS_TOTAL 16
75 #elif defined(NRF52833_XXAA)
76 #define RAM_SECTION_UNIT_SIZE 4096
77 #define RAM_UNIFORM_BLOCKS 8
78 #define RAM_UNIFORM_SECTIONS_PER_BLOCK 2
79 #define RAM_UNIFORM_SECTIONS_TOTAL 16
80 #define RAM_NON_UNIFORM_BLOCK_INDEX 8
81 #define RAM_NON_UNIFORM_BLOCK_UNITS 8
82 #define RAM_NON_UNIFORM_SECTIONS \
83 NRFX_LISTIFY(RAM_NON_UNIFORM_BLOCK_UNITS, \
84 RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
85 RAM_NON_UNIFORM_BLOCK_INDEX, 0), /* Section 0 of block 8 - 8 * 4 kB units. */ \
86 NRFX_LISTIFY(RAM_NON_UNIFORM_BLOCK_UNITS, \
87 RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
88 RAM_NON_UNIFORM_BLOCK_INDEX, 1) /* Section 1 of block 8 - 8 * 4 kB units. */
89 #elif defined(NRF52840_XXAA)
90 #define RAM_SECTION_UNIT_SIZE 4096
91 #define RAM_UNIFORM_BLOCKS 8
92 #define RAM_UNIFORM_SECTIONS_PER_BLOCK 2
93 #define RAM_UNIFORM_SECTIONS_TOTAL 16
94 #define RAM_NON_UNIFORM_BLOCK_INDEX 8
95 #define RAM_NON_UNIFORM_BLOCK_UNITS 8
96 #define RAM_NON_UNIFORM_SECTIONS \
97 NRFX_LISTIFY(RAM_NON_UNIFORM_BLOCK_UNITS, \
98 RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
99 RAM_NON_UNIFORM_BLOCK_INDEX, 0), /* Section 0 of block 8 - 8 * 4 kB units. */ \
100 NRFX_LISTIFY(RAM_NON_UNIFORM_BLOCK_UNITS, \
101 RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
102 RAM_NON_UNIFORM_BLOCK_INDEX, 1), /* Section 1 of block 8 - 8 * 4 kB units. */ \
103 NRFX_LISTIFY(RAM_NON_UNIFORM_BLOCK_UNITS, \
104 RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
105 RAM_NON_UNIFORM_BLOCK_INDEX, 2), /* Section 2 of block 8 - 8 * 4 kB units. */ \
106 NRFX_LISTIFY(RAM_NON_UNIFORM_BLOCK_UNITS, \
107 RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
108 RAM_NON_UNIFORM_BLOCK_INDEX, 3), /* Section 3 of block 8 - 8 * 4 kB units. */ \
109 NRFX_LISTIFY(RAM_NON_UNIFORM_BLOCK_UNITS, \
110 RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
111 RAM_NON_UNIFORM_BLOCK_INDEX, 4), /* Section 4 of block 8 - 8 * 4 kB units. */ \
112 NRFX_LISTIFY(RAM_NON_UNIFORM_BLOCK_UNITS, \
113 RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
114 RAM_NON_UNIFORM_BLOCK_INDEX, 5) /* Section 5 of block 8 - 8 * 4 kB units. */
115 #elif defined(NRF5340_XXAA_APPLICATION)
116 #define RAM_SECTION_UNIT_SIZE 4096
117 #define RAM_UNIFORM_BLOCKS 8
118 #define RAM_UNIFORM_SECTIONS_PER_BLOCK 16
119 #define RAM_UNIFORM_SECTIONS_TOTAL 128
120 #elif defined(NRF5340_XXAA_NETWORK)
121 #define RAM_SECTION_UNIT_SIZE 4096
122 #define RAM_UNIFORM_BLOCKS 4
123 #define RAM_UNIFORM_SECTIONS_PER_BLOCK 4
124 #define RAM_UNIFORM_SECTIONS_TOTAL 16
125 #elif defined(NRF54H20_ENGA_XXAA)
126 #define RAM_SECTION_UNIT_SIZE (32UL * 1024UL)
127 #define RAM_UNIFORM_BLOCKS 1
128 #define RAM_UNIFORM_SECTIONS_PER_BLOCK 1
129 #define RAM_UNIFORM_SECTIONS_TOTAL 1
130 #elif defined(NRF54L15_XXAA) || defined(NRF54L15_ENGA_XXAA)
131 #define RAM_SECTION_UNIT_SIZE (16UL * 1024UL)
132 #define RAM_NON_UNIFORM_SECTIONS \
133 NRFX_LISTIFY(4, RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
134 0, 0), /* Section 0 of block 0 - 4 * 16 kB units. */ \
135 NRFX_LISTIFY(4, RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
136 0, 1), /* Section 1 of block 0 - 4 * 16 kB units. */ \
137 NRFX_LISTIFY(2, RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
138 1, 0), /* Section 0 of block 1 - 2 * 16 kB units. */ \
139 NRFX_LISTIFY(2, RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
140 1, 1), /* Section 1 of block 1 - 2 * 16 kB units. */ \
141 NRFX_LISTIFY(1, RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
142 1, 2), /* Section 2 of block 1 - 1 * 16 kB units. */ \
143 NRFX_LISTIFY(1, RAM_NON_UNIFORM_SECTION_DECLARE, (,), \
144 1, 3) /* Section 3 of block 1 - 1 * 16 kB units. */
145 #elif defined(NRF9120_XXAA) || defined(NRF9160_XXAA)
146 #define RAM_SECTION_UNIT_SIZE 8192
147 #define RAM_UNIFORM_BLOCKS 8
148 #define RAM_UNIFORM_SECTIONS_PER_BLOCK 4
149 #define RAM_UNIFORM_SECTIONS_TOTAL 32
150 #elif !defined(RAM_SECTION_UNIT_SIZE)
151 #error "Unsupported device."
152 #endif
153
154 #define RAM_UNIFORM_SECTION_DECLARE(i, ...) \
155 {.decoded = {i / RAM_UNIFORM_SECTIONS_PER_BLOCK, i % RAM_UNIFORM_SECTIONS_PER_BLOCK}}
156
157 #if defined(RAM_NON_UNIFORM_SECTIONS)
158 static const ram_unit_t unit_to_block_section_lut[] =
159 {
160 #if defined(RAM_UNIFORM_SECTIONS_TOTAL)
161 NRFX_LISTIFY(RAM_UNIFORM_SECTIONS_TOTAL, RAM_UNIFORM_SECTION_DECLARE, (,)),
162 #endif
163 RAM_NON_UNIFORM_SECTIONS,
164 };
165 #endif
166
167 typedef void (* ram_ctrl_block_section_op_t)(uint8_t block_idx,
168 uint32_t section_mask,
169 bool enable);
170
ram_ctrl_block_section_power_enable_set(uint8_t block_idx,uint32_t section_mask,bool enable)171 static void ram_ctrl_block_section_power_enable_set(uint8_t block_idx,
172 uint32_t section_mask,
173 bool enable)
174 {
175 nrfx_ram_ctrl_section_power_mask_enable_set(block_idx, section_mask, enable);
176 }
177
ram_ctrl_block_section_retention_enable_set(uint8_t block_idx,uint32_t section_mask,bool enable)178 static void ram_ctrl_block_section_retention_enable_set(uint8_t block_idx,
179 uint32_t section_mask,
180 bool enable)
181 {
182 nrfx_ram_ctrl_section_retention_mask_enable_set(block_idx, section_mask, enable);
183 }
184
ram_ctrl_block_section_iterate(void const * p_object,size_t length,bool enable,ram_ctrl_block_section_op_t handler)185 static void ram_ctrl_block_section_iterate(void const * p_object,
186 size_t length,
187 bool enable,
188 ram_ctrl_block_section_op_t handler)
189 {
190 NRFX_ASSERT(nrfx_is_in_ram(p_object));
191 NRFX_ASSERT(length);
192
193 size_t rel_obj_adr = (size_t)p_object - NRF_MEMORY_RAM_BASE;
194 size_t obj_start_addr = rel_obj_adr;
195 size_t obj_end_addr = rel_obj_adr + length;
196
197 /* Handle case when the object is aligned to section boundaries,
198 * which could cause additional section being incorrectly iterated over. */
199 obj_end_addr--;
200
201 size_t ram_unit_start_idx = obj_start_addr / RAM_SECTION_UNIT_SIZE;
202 size_t ram_unit_end_idx = obj_end_addr / RAM_SECTION_UNIT_SIZE;
203
204 uint8_t block;
205 uint8_t section;
206 ram_unit_t prev_ram_unit = {.raw = UINT8_MAX};
207 for (size_t idx = ram_unit_start_idx; idx <= ram_unit_end_idx; idx++)
208 {
209 #if defined(RAM_NON_UNIFORM_SECTIONS)
210 ram_unit_t const * p_ram_unit = &unit_to_block_section_lut[idx];
211 block = p_ram_unit->decoded.block;
212 section = p_ram_unit->decoded.section;
213
214 ram_unit_t prev_ram_unit_copy = prev_ram_unit;
215 prev_ram_unit.raw = p_ram_unit->raw;
216 if (p_ram_unit->raw == prev_ram_unit_copy.raw)
217 {
218 continue;
219 }
220 #else
221 block = (uint8_t)idx / RAM_UNIFORM_SECTIONS_PER_BLOCK;
222 section = idx % RAM_UNIFORM_SECTIONS_PER_BLOCK;
223 (void)prev_ram_unit;
224 #endif
225 handler(block, 1UL << section, enable);
226 }
227 }
228
nrfx_ram_ctrl_power_enable_set(void const * p_object,size_t length,bool enable)229 void nrfx_ram_ctrl_power_enable_set(void const * p_object, size_t length, bool enable)
230 {
231 ram_ctrl_block_section_iterate(p_object,
232 length,
233 enable,
234 ram_ctrl_block_section_power_enable_set);
235 }
236
nrfx_ram_ctrl_retention_enable_set(void const * p_object,size_t length,bool enable)237 void nrfx_ram_ctrl_retention_enable_set(void const * p_object, size_t length, bool enable)
238 {
239 ram_ctrl_block_section_iterate(p_object,
240 length,
241 enable,
242 ram_ctrl_block_section_retention_enable_set);
243 }
244