1 /*
2  * Copyright (c) 2023, Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT zephyr_retained_ram
8 
9 #include <string.h>
10 #include <zephyr/device.h>
11 #include <zephyr/devicetree.h>
12 #include <zephyr/drivers/retained_mem.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/sys/util.h>
15 #include <zephyr/logging/log.h>
16 
17 LOG_MODULE_REGISTER(retained_mem_zephyr_ram, CONFIG_RETAINED_MEM_LOG_LEVEL);
18 
19 #ifdef CONFIG_RETAINED_MEM_MUTEXES
20 struct zephyr_retained_mem_ram_data {
21 	struct k_mutex lock;
22 };
23 #endif
24 
25 struct zephyr_retained_mem_ram_config {
26 	uint8_t *address;
27 	size_t size;
28 };
29 
zephyr_retained_mem_ram_lock_take(const struct device * dev)30 static inline void zephyr_retained_mem_ram_lock_take(const struct device *dev)
31 {
32 #ifdef CONFIG_RETAINED_MEM_MUTEXES
33 	struct zephyr_retained_mem_ram_data *data = dev->data;
34 
35 	k_mutex_lock(&data->lock, K_FOREVER);
36 #else
37 	ARG_UNUSED(dev);
38 #endif
39 }
40 
zephyr_retained_mem_ram_lock_release(const struct device * dev)41 static inline void zephyr_retained_mem_ram_lock_release(const struct device *dev)
42 {
43 #ifdef CONFIG_RETAINED_MEM_MUTEXES
44 	struct zephyr_retained_mem_ram_data *data = dev->data;
45 
46 	k_mutex_unlock(&data->lock);
47 #else
48 	ARG_UNUSED(dev);
49 #endif
50 }
51 
zephyr_retained_mem_ram_init(const struct device * dev)52 static int zephyr_retained_mem_ram_init(const struct device *dev)
53 {
54 #ifdef CONFIG_RETAINED_MEM_MUTEXES
55 	struct zephyr_retained_mem_ram_data *data = dev->data;
56 
57 	k_mutex_init(&data->lock);
58 #endif
59 
60 	return 0;
61 }
62 
zephyr_retained_mem_ram_size(const struct device * dev)63 static ssize_t zephyr_retained_mem_ram_size(const struct device *dev)
64 {
65 	const struct zephyr_retained_mem_ram_config *config = dev->config;
66 
67 	return (ssize_t)config->size;
68 }
69 
zephyr_retained_mem_ram_read(const struct device * dev,off_t offset,uint8_t * buffer,size_t size)70 static int zephyr_retained_mem_ram_read(const struct device *dev, off_t offset, uint8_t *buffer,
71 					size_t size)
72 {
73 	const struct zephyr_retained_mem_ram_config *config = dev->config;
74 
75 	zephyr_retained_mem_ram_lock_take(dev);
76 
77 	memcpy(buffer, (config->address + offset), size);
78 
79 	zephyr_retained_mem_ram_lock_release(dev);
80 
81 	return 0;
82 }
83 
zephyr_retained_mem_ram_write(const struct device * dev,off_t offset,const uint8_t * buffer,size_t size)84 static int zephyr_retained_mem_ram_write(const struct device *dev, off_t offset,
85 					 const uint8_t *buffer, size_t size)
86 {
87 	const struct zephyr_retained_mem_ram_config *config = dev->config;
88 
89 	zephyr_retained_mem_ram_lock_take(dev);
90 
91 	memcpy((config->address + offset), buffer, size);
92 
93 	zephyr_retained_mem_ram_lock_release(dev);
94 
95 	return 0;
96 }
97 
zephyr_retained_mem_ram_clear(const struct device * dev)98 static int zephyr_retained_mem_ram_clear(const struct device *dev)
99 {
100 	const struct zephyr_retained_mem_ram_config *config = dev->config;
101 
102 	zephyr_retained_mem_ram_lock_take(dev);
103 
104 	memset(config->address, 0, config->size);
105 
106 	zephyr_retained_mem_ram_lock_release(dev);
107 
108 	return 0;
109 }
110 
111 static const struct retained_mem_driver_api zephyr_retained_mem_ram_api = {
112 	.size = zephyr_retained_mem_ram_size,
113 	.read = zephyr_retained_mem_ram_read,
114 	.write = zephyr_retained_mem_ram_write,
115 	.clear = zephyr_retained_mem_ram_clear,
116 };
117 
118 #define ZEPHYR_RETAINED_MEM_RAM_DEVICE(inst)							\
119 	IF_ENABLED(CONFIG_RETAINED_MEM_MUTEXES,							\
120 		   (static struct zephyr_retained_mem_ram_data					\
121 		    zephyr_retained_mem_ram_data_##inst;)					\
122 	)											\
123 	static const struct zephyr_retained_mem_ram_config					\
124 			zephyr_retained_mem_ram_config_##inst = {				\
125 		.address = (uint8_t *)DT_REG_ADDR(DT_PARENT(DT_INST(inst, DT_DRV_COMPAT))),	\
126 		.size = DT_REG_SIZE(DT_PARENT(DT_INST(inst, DT_DRV_COMPAT))),			\
127 	};											\
128 	DEVICE_DT_INST_DEFINE(inst,								\
129 			      &zephyr_retained_mem_ram_init,					\
130 			      NULL,								\
131 			      COND_CODE_1(CONFIG_RETAINED_MEM_MUTEXES,				\
132 					  (&zephyr_retained_mem_ram_data_##inst), (NULL)	\
133 			      ),								\
134 			      &zephyr_retained_mem_ram_config_##inst,				\
135 			      POST_KERNEL,							\
136 			      CONFIG_RETAINED_MEM_INIT_PRIORITY,				\
137 			      &zephyr_retained_mem_ram_api);
138 
139 DT_INST_FOREACH_STATUS_OKAY(ZEPHYR_RETAINED_MEM_RAM_DEVICE)
140