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(&copy_in, request, sizeof(copy_in)));
302 			request = &copy_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 = &copy_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