1 /*
2  * Copyright (c) 2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "retained.h"
8 
9 #include <stdint.h>
10 #include <string.h>
11 
12 #include <zephyr/kernel.h>
13 #include <zephyr/devicetree.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <zephyr/sys/crc.h>
16 
17 #include <hal/nrf_power.h>
18 
19 /* nRF52 RAM (really, RAM AHB slaves) are partitioned as:
20  * * Up to 8 blocks of two 4 KiBy byte "small" sections
21  * * A 9th block of with 32 KiBy "large" sections
22  *
23  * At time of writing the maximum number of large sections is 6, all
24  * within the first large block.  Theoretically there could be more
25  * sections in the 9th block, and possibly more blocks.
26  */
27 
28 /* Inclusive address of RAM start */
29 #define SRAM_BEGIN (uintptr_t)DT_REG_ADDR(DT_NODELABEL(sram0))
30 
31 /* Exclusive address of RAM end */
32 #define SRAM_END (SRAM_BEGIN + (uintptr_t)DT_REG_SIZE(DT_NODELABEL(sram0)))
33 
34 /* Size of a controllable RAM section in the small blocks */
35 #define SMALL_SECTION_SIZE 4096
36 
37 /* Number of controllable RAM sections in each of the lower blocks */
38 #define SMALL_SECTIONS_PER_BLOCK 2
39 
40 /* Span of a small block */
41 #define SMALL_BLOCK_SIZE (SMALL_SECTIONS_PER_BLOCK * SMALL_SECTION_SIZE)
42 
43 /* Number of small blocks */
44 #define SMALL_BLOCK_COUNT 8
45 
46 /* Span of the SRAM area covered by small sections */
47 #define SMALL_SECTION_SPAN (SMALL_BLOCK_COUNT * SMALL_BLOCK_SIZE)
48 
49 /* Inclusive address of the RAM range covered by large sections */
50 #define LARGE_SECTION_BEGIN (SRAM_BEGIN + SMALL_SECTION_SPAN)
51 
52 /* Size of a controllable RAM section in large blocks */
53 #define LARGE_SECTION_SIZE 32768
54 
55 /* Set or clear RAM retention in SYSTEM_OFF for the provided object.
56  *
57  * @note This only works for nRF52 with the POWER module.  The other
58  * Nordic chips use a different low-level API, which is not currently
59  * used by this function.
60  *
61  * @param ptr pointer to the start of the retainable object
62  *
63  * @param len length of the retainable object
64  *
65  * @param enable true to enable retention, false to clear retention
66  */
ram_range_retain(const void * ptr,size_t len,bool enable)67 static int ram_range_retain(const void *ptr,
68 			    size_t len,
69 			    bool enable)
70 {
71 	uintptr_t addr = (uintptr_t)ptr;
72 	uintptr_t addr_end = addr + len;
73 
74 	/* Error if the provided range is empty or doesn't lie
75 	 * entirely within the SRAM address space.
76 	 */
77 	if ((len == 0U)
78 	    || (addr < SRAM_BEGIN)
79 	    || (addr > (SRAM_END - len))) {
80 		return -EINVAL;
81 	}
82 
83 	/* Iterate over each section covered by the range, setting the
84 	 * corresponding RAM OFF retention bit in the parent block.
85 	 */
86 	do {
87 		uintptr_t block_base = SRAM_BEGIN;
88 		uint32_t section_size = SMALL_SECTION_SIZE;
89 		uint32_t sections_per_block = SMALL_SECTIONS_PER_BLOCK;
90 		bool is_large = (addr >= LARGE_SECTION_BEGIN);
91 		uint8_t block = 0;
92 
93 		if (is_large) {
94 			block = 8;
95 			block_base = LARGE_SECTION_BEGIN;
96 			section_size = LARGE_SECTION_SIZE;
97 
98 			/* RAM[x] supports only 16 sections, each its own bit
99 			 * for POWER (0..15) and RETENTION (16..31).  We don't
100 			 * know directly how many sections are present, so
101 			 * assume they all are; the true limit will be
102 			 * determined by the SRAM size.
103 			 */
104 			sections_per_block = 16;
105 		}
106 
107 		uint32_t section = (addr - block_base) / section_size;
108 
109 		if (section >= sections_per_block) {
110 			block += section / sections_per_block;
111 			section %= sections_per_block;
112 		}
113 
114 		uint32_t section_mask =
115 			(POWER_RAM_POWERSET_S0RETENTION_On
116 					 << (section + POWER_RAM_POWERSET_S0RETENTION_Pos));
117 
118 		if (enable) {
119 			nrf_power_rampower_mask_on(NRF_POWER, block, section_mask);
120 		} else {
121 			nrf_power_rampower_mask_off(NRF_POWER, block, section_mask);
122 		}
123 
124 		/* Move to the first address in the next section. */
125 		addr += section_size - (addr % section_size);
126 	} while (addr < addr_end);
127 
128 	return 0;
129 }
130 
131 /* Retained data must be defined in a no-init section to prevent the C
132  * runtime initialization from zeroing it before anybody can see it.
133  */
134 __noinit struct retained_data retained;
135 
136 #define RETAINED_CRC_OFFSET offsetof(struct retained_data, crc)
137 #define RETAINED_CHECKED_SIZE (RETAINED_CRC_OFFSET + sizeof(retained.crc))
138 
retained_validate(void)139 bool retained_validate(void)
140 {
141 	/* The residue of a CRC is what you get from the CRC over the
142 	 * message catenated with its CRC.  This is the post-final-xor
143 	 * residue for CRC-32 (CRC-32/ISO-HDLC) which Zephyr calls
144 	 * crc32_ieee.
145 	 */
146 	const uint32_t residue = 0x2144df1c;
147 	uint32_t crc = crc32_ieee((const uint8_t *)&retained,
148 				  RETAINED_CHECKED_SIZE);
149 	bool valid = (crc == residue);
150 
151 	/* If the CRC isn't valid, reset the retained data. */
152 	if (!valid) {
153 		memset(&retained, 0, sizeof(retained));
154 	}
155 
156 	/* Reset to accrue runtime from this session. */
157 	retained.uptime_latest = 0;
158 
159 	/* Reconfigure to retain the state during system off, regardless of
160 	 * whether validation succeeded.  Although these values can sometimes
161 	 * be observed to be preserved across System OFF, the product
162 	 * specification states they are not retained in that situation, and
163 	 * that can also be observed.
164 	 */
165 	(void)ram_range_retain(&retained, RETAINED_CHECKED_SIZE, true);
166 
167 	return valid;
168 }
169 
retained_update(void)170 void retained_update(void)
171 {
172 	uint64_t now = k_uptime_ticks();
173 
174 	retained.uptime_sum += (now - retained.uptime_latest);
175 	retained.uptime_latest = now;
176 
177 	uint32_t crc = crc32_ieee((const uint8_t *)&retained,
178 				  RETAINED_CRC_OFFSET);
179 
180 	retained.crc = sys_cpu_to_le32(crc);
181 }
182