1 /*
2 * Copyright (c) 2024 Renesas Electronics Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <sys/types.h>
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/flash/ra_flash_api_extensions.h>
10 #include <zephyr/kernel.h>
11
12 #ifdef CONFIG_USERSPACE
13 #include <zephyr/syscall.h>
14 #include <zephyr/syscall_handler.h>
15 #endif
16
17 #include <soc.h>
18 #include "flash_hp_ra.h"
19
20 #define FLASH_HP_CONFIG_SET_ACCESS_WORD_CNT (8U)
21
22 #if (DT_PROP(DT_NODELABEL(flash0), renesas_programming_enable))
23 extern uint16_t g_configuration_area_data[FLASH_HP_CONFIG_SET_ACCESS_WORD_CNT];
24 #endif
25 extern fsp_err_t
26 flash_hp_enter_pe_cf_mode(flash_hp_instance_ctrl_t *const p_ctrl) PLACE_IN_RAM_SECTION;
27
28 extern fsp_err_t flash_hp_stop(void) PLACE_IN_RAM_SECTION;
29
30 extern fsp_err_t flash_hp_configuration_area_write(flash_hp_instance_ctrl_t *p_ctrl,
31 uint32_t fsaddr) PLACE_IN_RAM_SECTION;
32
33 extern fsp_err_t flash_hp_check_errors(fsp_err_t previous_error, uint32_t error_bits,
34 fsp_err_t return_error) PLACE_IN_RAM_SECTION;
35
36 extern fsp_err_t flash_hp_pe_mode_exit(void) PLACE_IN_RAM_SECTION;
37
38 static fsp_err_t flash_hp_set_block_protect_ns(flash_hp_instance_ctrl_t *p_ctrl,
39 uint8_t *bps_val_ns, uint8_t *pbps_val_ns,
40 uint32_t size) PLACE_IN_RAM_SECTION;
41
42 static fsp_err_t flash_hp_set_block_protect_sec(flash_hp_instance_ctrl_t *p_ctrl,
43 uint8_t *bps_val_sec, uint8_t *pbps_val_sec,
44 uint32_t size) PLACE_IN_RAM_SECTION;
45
46 static fsp_err_t flash_hp_set_block_protect_sel(flash_hp_instance_ctrl_t *p_ctrl,
47 uint8_t *bps_sel_val,
48 uint32_t size) PLACE_IN_RAM_SECTION;
49
flash_hp_set_block_protect_ns(flash_hp_instance_ctrl_t * p_ctrl,uint8_t * bps_val_ns,uint8_t * pbps_val_ns,uint32_t size)50 static fsp_err_t flash_hp_set_block_protect_ns(flash_hp_instance_ctrl_t *p_ctrl,
51 uint8_t *bps_val_ns, uint8_t *pbps_val_ns,
52 uint32_t size)
53 {
54 /* Disable interrupts to prevent vector table access while code flash is in P/E mode. */
55 int key = irq_lock();
56
57 /* Update Flash state and enter Code Flash P/E mode */
58 fsp_err_t err = flash_hp_enter_pe_cf_mode(p_ctrl);
59
60 FSP_ERROR_RETURN(err == FSP_SUCCESS, err);
61
62 memset(g_configuration_area_data, UINT8_MAX, sizeof(g_configuration_area_data));
63 if (bps_val_ns != NULL) {
64 memcpy(&g_configuration_area_data[FLASH_HP_FCU_CONFIG_SET_BPS_OFFSET], bps_val_ns,
65 size);
66 err = flash_hp_configuration_area_write(p_ctrl, FLASH_HP_FCU_CONFIG_SET_BPS);
67 err = flash_hp_check_errors(err, 0, FSP_ERR_WRITE_FAILED);
68 }
69
70 memset(g_configuration_area_data, UINT8_MAX, sizeof(g_configuration_area_data));
71 if (pbps_val_ns != NULL) {
72 memcpy(&g_configuration_area_data[FLASH_HP_FCU_CONFIG_SET_BPS_OFFSET], pbps_val_ns,
73 size);
74 err = flash_hp_configuration_area_write(p_ctrl, FLASH_HP_FCU_CONFIG_SET_PBPS);
75 err = flash_hp_check_errors(err, 0, FSP_ERR_WRITE_FAILED);
76 }
77
78 /* Return to read mode*/
79 fsp_err_t pe_exit_err = flash_hp_pe_mode_exit();
80
81 if (err == FSP_SUCCESS) {
82 err = pe_exit_err;
83 }
84
85 /* Enable interrupts after code flash operations are complete. */
86 irq_unlock(key);
87
88 return err;
89 }
90
flash_hp_set_block_protect_sec(flash_hp_instance_ctrl_t * p_ctrl,uint8_t * bps_val_sec,uint8_t * pbps_val_sec,uint32_t size)91 static fsp_err_t flash_hp_set_block_protect_sec(flash_hp_instance_ctrl_t *p_ctrl,
92 uint8_t *bps_val_sec, uint8_t *pbps_val_sec,
93 uint32_t size)
94 {
95 /* Disable interrupts to prevent vector table access while code flash is in P/E mode. */
96 int key = irq_lock();
97 /* Update Flash state and enter Code Flash P/E mode */
98 fsp_err_t err = flash_hp_enter_pe_cf_mode(p_ctrl);
99
100 FSP_ERROR_RETURN(err == FSP_SUCCESS, err);
101
102 memset(g_configuration_area_data, UINT8_MAX, sizeof(g_configuration_area_data));
103 if (bps_val_sec != NULL) {
104 memcpy(&g_configuration_area_data[FLASH_HP_FCU_CONFIG_SET_BPS_OFFSET], bps_val_sec,
105 size);
106 err = flash_hp_configuration_area_write(p_ctrl, FLASH_HP_FCU_CONFIG_SET_BPS_SEC);
107 err = flash_hp_check_errors(err, 0, FSP_ERR_WRITE_FAILED);
108 }
109
110 memset(g_configuration_area_data, UINT8_MAX, sizeof(g_configuration_area_data));
111 if (pbps_val_sec != NULL) {
112 memcpy(&g_configuration_area_data[FLASH_HP_FCU_CONFIG_SET_BPS_OFFSET], pbps_val_sec,
113 size);
114 err = flash_hp_configuration_area_write(p_ctrl, FLASH_HP_FCU_CONFIG_SET_PBPS_SEC);
115 err = flash_hp_check_errors(err, 0, FSP_ERR_WRITE_FAILED);
116 }
117
118 /* Return to read mode*/
119 fsp_err_t pe_exit_err = flash_hp_pe_mode_exit();
120
121 if (err == FSP_SUCCESS) {
122 err = pe_exit_err;
123 }
124
125 /* Enable interrupts after code flash operations are complete. */
126 irq_unlock(key);
127
128 return err;
129 }
130
flash_hp_set_block_protect_sel(flash_hp_instance_ctrl_t * p_ctrl,uint8_t * bps_sel_val,uint32_t size)131 static fsp_err_t flash_hp_set_block_protect_sel(flash_hp_instance_ctrl_t *p_ctrl,
132 uint8_t *bps_sel_val, uint32_t size)
133 {
134 /* Disable interrupts to prevent vector table access while code flash is in P/E mode. */
135 int key = irq_lock();
136
137 /* Update Flash state and enter Code Flash P/E mode */
138 fsp_err_t err = flash_hp_enter_pe_cf_mode(p_ctrl);
139
140 FSP_ERROR_RETURN(err == FSP_SUCCESS, err);
141
142 memset(g_configuration_area_data, UINT8_MAX, sizeof(g_configuration_area_data));
143 memcpy(&g_configuration_area_data[FLASH_HP_FCU_CONFIG_SET_BPS_OFFSET], bps_sel_val, size);
144 err = flash_hp_configuration_area_write(p_ctrl, FLASH_HP_FCU_CONFIG_SET_BPS_SEL);
145 err = flash_hp_check_errors(err, 0, FSP_ERR_WRITE_FAILED);
146
147 /* Return to read mode*/
148 fsp_err_t pe_exit_err = flash_hp_pe_mode_exit();
149
150 if (err == FSP_SUCCESS) {
151 err = pe_exit_err;
152 }
153
154 /* Enable interrupts after code flash operations are complete. */
155 irq_unlock(key);
156
157 return err;
158 }
159
160 static fsp_err_t R_FLASH_HP_BlockProtectSet(flash_ctrl_t *const p_api_ctrl, uint8_t *bps_val_ns,
161 uint8_t *bps_val_sec, uint8_t *bps_val_sel,
162 uint8_t *pbps_val_ns, uint8_t *pbps_val_sec,
163 uint32_t size);
164
165 static fsp_err_t R_FLASH_HP_BlockProtectGet(flash_ctrl_t *const p_api_ctrl, uint32_t *bps_val_ns,
166 uint32_t *bps_val_sec, uint8_t *bps_val_sel,
167 uint8_t *pbps_val_ns, uint8_t *pbps_val_sec,
168 uint32_t *size);
169
170 int flash_ra_block_protect_set(const struct device *dev,
171 const struct flash_ra_ex_write_protect_in *request);
172
173 int flash_ra_block_protect_get(const struct device *dev,
174 struct flash_ra_ex_write_protect_out *response);
175
R_FLASH_HP_BlockProtectSet(flash_ctrl_t * const p_api_ctrl,uint8_t * bps_val_ns,uint8_t * bps_val_sec,uint8_t * bps_val_sel,uint8_t * pbps_val_ns,uint8_t * pbps_val_sec,uint32_t size)176 static fsp_err_t R_FLASH_HP_BlockProtectSet(flash_ctrl_t *const p_api_ctrl, uint8_t *bps_val_ns,
177 uint8_t *bps_val_sec, uint8_t *bps_val_sel,
178 uint8_t *pbps_val_ns, uint8_t *pbps_val_sec,
179 uint32_t size)
180 {
181 flash_hp_instance_ctrl_t *p_ctrl = (flash_hp_instance_ctrl_t *)p_api_ctrl;
182 fsp_err_t err = FSP_SUCCESS;
183
184 #if (DT_PROP(DT_NODELABEL(flash0), renesas_programming_enable))
185
186 /* if non-secure BPS (PBPS) buffers are not null and size is smaller than 16 bytes */
187 if (((bps_val_ns != NULL) || (pbps_val_ns != NULL)) &&
188 (size <= (sizeof(uint16_t) * FLASH_HP_CONFIG_SET_ACCESS_WORD_CNT))) {
189 err = flash_hp_set_block_protect_ns(p_ctrl, bps_val_ns, pbps_val_ns, size);
190 }
191
192 /* if secure BPS (PBPS) buffers are not null and size is smaller than 16 bytes */
193 if (((bps_val_sec != NULL) || (pbps_val_sec != NULL)) &&
194 (size <= (sizeof(uint16_t) * FLASH_HP_CONFIG_SET_ACCESS_WORD_CNT))) {
195 err = flash_hp_set_block_protect_sec(p_ctrl, bps_val_sec, pbps_val_sec, size);
196 }
197
198 /* if BPS SEL buffer is not null and size is smaller than 16 bytes */
199 if ((bps_val_sel != NULL) &&
200 (size <= (sizeof(uint16_t) * FLASH_HP_CONFIG_SET_ACCESS_WORD_CNT))) {
201 err = flash_hp_set_block_protect_sel(p_ctrl, bps_val_sel, size);
202 }
203 #else
204
205 err = FSP_ERR_UNSUPPORTED; /* For consistency with _LP API we return error if Code Flash */
206
207 #endif
208
209 return err;
210 }
211
R_FLASH_HP_BlockProtectGet(flash_ctrl_t * const p_api_ctrl,uint32_t * bps_val_ns,uint32_t * bps_val_sec,uint8_t * bps_val_sel,uint8_t * pbps_val_ns,uint8_t * pbps_val_sec,uint32_t * size)212 static fsp_err_t R_FLASH_HP_BlockProtectGet(flash_ctrl_t *const p_api_ctrl, uint32_t *bps_val_ns,
213 uint32_t *bps_val_sec, uint8_t *bps_val_sel,
214 uint8_t *pbps_val_ns, uint8_t *pbps_val_sec,
215 uint32_t *size)
216 {
217 fsp_err_t err = FSP_ERR_UNSUPPORTED;
218
219 #if (DT_PROP(DT_NODELABEL(flash0), renesas_programming_enable))
220
221 err = FSP_SUCCESS;
222
223 if (bps_val_ns != NULL) {
224 bps_val_ns[0] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS + 0));
225 bps_val_ns[1] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS + 3));
226 bps_val_ns[2] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS + 7));
227 bps_val_ns[3] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS + 11));
228 }
229
230 if (bps_val_sec != NULL) {
231 bps_val_sec[0] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEC + 0));
232 bps_val_sec[1] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEC + 3));
233 bps_val_sec[2] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEC + 7));
234 bps_val_sec[3] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEC + 11));
235 }
236
237 if (bps_val_sel != NULL) {
238 bps_val_sel[0] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEL + 0));
239 bps_val_sel[1] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEL + 3));
240 bps_val_sel[2] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEL + 7));
241 bps_val_sel[3] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEL + 11));
242 }
243
244 if (pbps_val_ns != NULL) {
245 pbps_val_ns[0] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS + 0));
246 pbps_val_ns[1] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS + 3));
247 pbps_val_ns[2] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS + 7));
248 pbps_val_ns[3] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS + 11));
249 }
250
251 if (pbps_val_sec != NULL) {
252 pbps_val_sec[0] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS_SEC + 0));
253 pbps_val_sec[1] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS_SEC + 3));
254 pbps_val_sec[2] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS_SEC + 7));
255 pbps_val_sec[3] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS_SEC + 11));
256 }
257
258 if (size != NULL) {
259 *size = 4;
260 }
261 #endif
262
263 FSP_PARAMETER_NOT_USED(p_api_ctrl);
264
265 return err;
266 }
267
268 #if defined(CONFIG_FLASH_RA_WRITE_PROTECT)
flash_ra_block_protect_get(const struct device * dev,struct flash_ra_ex_write_protect_out * response)269 int flash_ra_block_protect_get(const struct device *dev,
270 struct flash_ra_ex_write_protect_out *response)
271 {
272 fsp_err_t err = FSP_ERR_ASSERTION;
273 struct flash_hp_ra_data *flash_data = dev->data;
274 struct flash_hp_ra_controller *dev_ctrl = flash_data->controller;
275 flash_ra_cf_block_map bps_ns;
276
277 /* get the current non-secure BPS register values */
278 err = R_FLASH_HP_BlockProtectGet(&dev_ctrl->flash_ctrl, (uint32_t *)&bps_ns, NULL, NULL,
279 NULL, NULL, NULL);
280 memcpy(&response->protected_enabled, &bps_ns, sizeof(flash_ra_cf_block_map));
281
282 return err;
283 }
284
flash_ra_ex_op_write_protect(const struct device * dev,const uintptr_t in,void * out)285 int flash_ra_ex_op_write_protect(const struct device *dev, const uintptr_t in, void *out)
286 {
287 const struct flash_ra_ex_write_protect_in *request =
288 (const struct flash_ra_ex_write_protect_in *)in;
289 struct flash_ra_ex_write_protect_out *result = (struct flash_ra_ex_write_protect_out *)out;
290
291 int rc = 0, rc2 = 0;
292 #ifdef CONFIG_USERSPACE
293 bool syscall_trap = z_syscall_trap();
294 #endif
295
296 if (request != NULL) {
297 #ifdef CONFIG_USERSPACE
298 struct flash_ra_ex_write_protect_in copy_in;
299
300 if (syscall_trap) {
301 Z_OOPS(z_user_from_copy(©_in, request, sizeof(copy_in)));
302 request = ©_in;
303 }
304 #endif
305 /* if both enable and disable are set */
306 if ((request->protect_enable.BPS[0] & request->protect_disable.BPS[0]) ||
307 (request->protect_enable.BPS[1] & request->protect_disable.BPS[1]) ||
308 (request->protect_enable.BPS[2] & request->protect_disable.BPS[2]) ||
309 (request->protect_enable.BPS[3] & request->protect_disable.BPS[3])) {
310 return EINVAL;
311 }
312
313 rc = flash_ra_block_protect_set(dev, request);
314 }
315
316 if (result != NULL) {
317 #ifdef CONFIG_USERSPACE
318 struct flash_ra_ex_write_protect_out copy_out;
319
320 if (syscall_trap) {
321 result = ©_out;
322 }
323 #endif
324 rc2 = flash_ra_block_protect_get(dev, result);
325 if (!rc) {
326 rc = rc2;
327 }
328
329 #ifdef CONFIG_USERSPACE
330 if (syscall_trap) {
331 Z_OOPS(z_user_to_copy(out, result, sizeof(copy_out)));
332 }
333 #endif
334 }
335
336 return rc;
337 }
338
flash_ra_block_protect_set(const struct device * dev,const struct flash_ra_ex_write_protect_in * request)339 int flash_ra_block_protect_set(const struct device *dev,
340 const struct flash_ra_ex_write_protect_in *request)
341 {
342 fsp_err_t err = FSP_ERR_ASSERTION;
343 struct flash_hp_ra_data *flash_data = dev->data;
344 struct flash_hp_ra_controller *dev_ctrl = flash_data->controller;
345 flash_ra_cf_block_map bps_ns;
346
347 /* get the current non-secure BPS register values */
348 err = R_FLASH_HP_BlockProtectGet(&dev_ctrl->flash_ctrl, (uint32_t *)&bps_ns, NULL, NULL,
349 NULL, NULL, NULL);
350
351 if (err != FSP_SUCCESS) {
352 __ASSERT(false, "flash: block get current value error =%d", err);
353 return -EIO;
354 }
355
356 /* enable block protect */
357 bps_ns.BPS[0] &= ~(request->protect_enable.BPS[0]);
358 bps_ns.BPS[1] &= ~(request->protect_enable.BPS[1]);
359 bps_ns.BPS[2] &= ~(request->protect_enable.BPS[2]);
360 bps_ns.BPS[3] &= ~(request->protect_enable.BPS[3]);
361
362 /* disable block protect */
363 bps_ns.BPS[0] |= (request->protect_disable.BPS[0]);
364 bps_ns.BPS[1] |= (request->protect_disable.BPS[1]);
365 bps_ns.BPS[2] |= (request->protect_disable.BPS[2]);
366 bps_ns.BPS[3] |= (request->protect_disable.BPS[3]);
367
368 /* reset default all from non-secure */
369 err = R_FLASH_HP_BlockProtectSet(&dev_ctrl->flash_ctrl, (uint8_t *)&bps_ns, NULL, NULL,
370 NULL, NULL, sizeof(bps_ns));
371
372 if (err != FSP_SUCCESS) {
373 __ASSERT(false, "flash: block protect error=%d", err);
374 return -EIO;
375 }
376 return 0;
377 }
378
379 #endif /* CONFIG_FLASH_RA_WRITE_PROTECT */
380