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