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