1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Public API for retained memory drivers
10 */
11
12 #ifndef ZEPHYR_INCLUDE_DRIVERS_RETAINED_MEM_
13 #define ZEPHYR_INCLUDE_DRIVERS_RETAINED_MEM_
14
15 #include <stdint.h>
16 #include <stddef.h>
17 #include <sys/types.h>
18 #include <zephyr/kernel.h>
19 #include <zephyr/device.h>
20 #include <zephyr/types.h>
21 #include <zephyr/sys/math_extras.h>
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27 BUILD_ASSERT(!(sizeof(off_t) > sizeof(size_t)),
28 "Size of off_t must be equal or less than size of size_t");
29
30 /**
31 * @brief Retained memory driver interface
32 * @defgroup retained_mem_interface Retained memory driver interface
33 * @ingroup io_interfaces
34 * @{
35 */
36
37 /**
38 * @typedef retained_mem_size_api
39 * @brief Callback API to get size of retained memory area.
40 * See retained_mem_size() for argument description.
41 */
42 typedef ssize_t (*retained_mem_size_api)(const struct device *dev);
43
44 /**
45 * @typedef retained_mem_read_api
46 * @brief Callback API to read from retained memory area.
47 * See retained_mem_read() for argument description.
48 */
49 typedef int (*retained_mem_read_api)(const struct device *dev, off_t offset, uint8_t *buffer,
50 size_t size);
51
52 /**
53 * @typedef retained_mem_write_api
54 * @brief Callback API to write to retained memory area.
55 * See retained_mem_write() for argument description.
56 */
57 typedef int (*retained_mem_write_api)(const struct device *dev, off_t offset,
58 const uint8_t *buffer, size_t size);
59
60 /**
61 * @typedef retained_mem_clear_api
62 * @brief Callback API to clear retained memory area (reset all data to 0x00).
63 * See retained_mem_clear() for argument description.
64 */
65 typedef int (*retained_mem_clear_api)(const struct device *dev);
66
67 /**
68 * @brief Retained memory driver API
69 * API which can be used by a device to store data in a retained memory area. Retained memory is
70 * memory that is retained while the device is powered but is lost when power to the device is
71 * lost (note that low power modes in some devices may clear the data also). This may be in a
72 * non-initialised RAM region, or in specific registers, but is not reset when a different
73 * application begins execution or the device is rebooted (without power loss). It must support
74 * byte-level reading and writing without a need to erase data before writing.
75 *
76 * Note that drivers must implement all functions, none of the functions are optional.
77 */
78 struct retained_mem_driver_api {
79 retained_mem_size_api size;
80 retained_mem_read_api read;
81 retained_mem_write_api write;
82 retained_mem_clear_api clear;
83 };
84
85 /**
86 * @brief Returns the size of the retained memory area.
87 *
88 * @param dev Retained memory device to use.
89 *
90 * @retval Positive value indicating size in bytes on success, else negative errno
91 * code.
92 */
93 __syscall ssize_t retained_mem_size(const struct device *dev);
94
z_impl_retained_mem_size(const struct device * dev)95 static inline ssize_t z_impl_retained_mem_size(const struct device *dev)
96 {
97 struct retained_mem_driver_api *api = (struct retained_mem_driver_api *)dev->api;
98
99 return api->size(dev);
100 }
101
102 /**
103 * @brief Reads data from the Retained memory area.
104 *
105 * @param dev Retained memory device to use.
106 * @param offset Offset to read data from.
107 * @param buffer Buffer to store read data in.
108 * @param size Size of data to read.
109 *
110 * @retval 0 on success else negative errno code.
111 */
112 __syscall int retained_mem_read(const struct device *dev, off_t offset, uint8_t *buffer,
113 size_t size);
114
z_impl_retained_mem_read(const struct device * dev,off_t offset,uint8_t * buffer,size_t size)115 static inline int z_impl_retained_mem_read(const struct device *dev, off_t offset,
116 uint8_t *buffer, size_t size)
117 {
118 struct retained_mem_driver_api *api = (struct retained_mem_driver_api *)dev->api;
119 size_t area_size;
120
121 /* Validate user-supplied parameters */
122 if (size == 0) {
123 return 0;
124 }
125
126 area_size = api->size(dev);
127
128 if (offset < 0 || size > area_size || (area_size - size) < (size_t)offset) {
129 return -EINVAL;
130 }
131
132 return api->read(dev, offset, buffer, size);
133 }
134
135 /**
136 * @brief Writes data to the Retained memory area - underlying data does not need to
137 * be cleared prior to writing.
138 *
139 * @param dev Retained memory device to use.
140 * @param offset Offset to write data to.
141 * @param buffer Data to write.
142 * @param size Size of data to be written.
143 *
144 * @retval 0 on success else negative errno code.
145 */
146 __syscall int retained_mem_write(const struct device *dev, off_t offset, const uint8_t *buffer,
147 size_t size);
148
z_impl_retained_mem_write(const struct device * dev,off_t offset,const uint8_t * buffer,size_t size)149 static inline int z_impl_retained_mem_write(const struct device *dev, off_t offset,
150 const uint8_t *buffer, size_t size)
151 {
152 struct retained_mem_driver_api *api = (struct retained_mem_driver_api *)dev->api;
153 size_t area_size;
154
155 /* Validate user-supplied parameters */
156 if (size == 0) {
157 return 0;
158 }
159
160 area_size = api->size(dev);
161
162 if (offset < 0 || size > area_size || (area_size - size) < (size_t)offset) {
163 return -EINVAL;
164 }
165
166 return api->write(dev, offset, buffer, size);
167 }
168
169 /**
170 * @brief Clears data in the retained memory area by setting it to 0x00.
171 *
172 * @param dev Retained memory device to use.
173 *
174 * @retval 0 on success else negative errno code.
175 */
176 __syscall int retained_mem_clear(const struct device *dev);
177
z_impl_retained_mem_clear(const struct device * dev)178 static inline int z_impl_retained_mem_clear(const struct device *dev)
179 {
180 struct retained_mem_driver_api *api = (struct retained_mem_driver_api *)dev->api;
181
182 return api->clear(dev);
183 }
184
185 /**
186 * @}
187 */
188
189 #ifdef __cplusplus
190 }
191 #endif
192
193 #include <syscalls/retained_mem.h>
194
195 #endif /* ZEPHYR_INCLUDE_DRIVERS_RETAINED_MEM_ */
196