1 /*
2  * Copyright (c) 2024-2025 Renesas Electronics Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL
8 #include <zephyr/logging/log.h>
9 #include <string.h>
10 #include <soc.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/device.h>
13 #include <zephyr/devicetree.h>
14 #include <zephyr/init.h>
15 #include <zephyr/irq.h>
16 #include "flash_hp_ra.h"
17 
18 #define DT_DRV_COMPAT renesas_ra_flash_hp_controller
19 
20 LOG_MODULE_REGISTER(flash_hp_ra, CONFIG_FLASH_LOG_LEVEL);
21 
22 #define ERASE_BLOCK_SIZE_0 DT_PROP(DT_INST(0, renesas_ra_nv_flash), erase_block_size)
23 #define ERASE_BLOCK_SIZE_1 DT_PROP(DT_INST(1, renesas_ra_nv_flash), erase_block_size)
24 
25 BUILD_ASSERT((ERASE_BLOCK_SIZE_0 % FLASH_HP_CF_BLOCK_8KB_SIZE) == 0,
26 	     "erase-block-size expected to be a multiple of a block size");
27 BUILD_ASSERT((ERASE_BLOCK_SIZE_1 % FLASH_HP_DF_BLOCK_SIZE) == 0,
28 	     "erase-block-size expected to be a multiple of a block size");
29 
30 /* Flags, set from Callback function */
31 static volatile struct event_flash g_event_flash = {
32 	.erase_complete = false,
33 	.write_complete = false,
34 };
35 
36 static struct flash_pages_layout flash_ra_layout[5];
37 
38 void fcu_frdyi_isr(void);
39 void fcu_fiferr_isr(void);
40 
bgo_callback(flash_callback_args_t * p_args)41 void bgo_callback(flash_callback_args_t *p_args)
42 {
43 	if (FLASH_EVENT_ERASE_COMPLETE == p_args->event) {
44 		g_event_flash.erase_complete = true;
45 	} else {
46 		g_event_flash.write_complete = true;
47 	}
48 }
49 
flash_ra_valid_range(struct flash_hp_ra_data * flash_data,off_t offset,size_t len)50 static bool flash_ra_valid_range(struct flash_hp_ra_data *flash_data, off_t offset, size_t len)
51 {
52 #if defined(CONFIG_DUAL_BANK_MODE)
53 	if (flash_data->FlashRegion == DATA_FLASH) {
54 		if ((offset < 0) || (offset >= flash_data->area_size) ||
55 		    (flash_data->area_size - offset < len) || (len > UINT32_MAX - offset)) {
56 			return false;
57 		}
58 	} else {
59 		if ((offset < 0) || (offset >= FLASH_HP_CF_DUAL_HIGH_END_ADDRESS) ||
60 		    (offset >= FLASH_HP_CF_DUAL_LOW_END_ADDRESS &&
61 		     offset < FLASH_HP_BANK2_OFFSET) ||
62 		    ((len + offset) > FLASH_HP_CF_DUAL_HIGH_END_ADDRESS) ||
63 		    ((len + offset) > FLASH_HP_CF_DUAL_LOW_END_ADDRESS &&
64 		     (len + offset) < FLASH_HP_BANK2_OFFSET) ||
65 		    (len > UINT32_MAX - offset)) {
66 			return false;
67 		}
68 	}
69 #else
70 	if ((offset < 0) || (offset >= flash_data->area_size) ||
71 	    (flash_data->area_size - offset < len) || (len > UINT32_MAX - offset)) {
72 		return false;
73 	}
74 #endif
75 	return true;
76 }
77 
flash_ra_read(const struct device * dev,off_t offset,void * data,size_t len)78 static int flash_ra_read(const struct device *dev, off_t offset, void *data, size_t len)
79 {
80 	struct flash_hp_ra_data *flash_data = dev->data;
81 
82 	if (!flash_ra_valid_range(flash_data, offset, len)) {
83 		return -EINVAL;
84 	}
85 
86 	if (!len) {
87 		return 0;
88 	}
89 
90 	LOG_DBG("flash: read 0x%lx, len: %u", (long)(offset + flash_data->area_address), len);
91 
92 	memcpy(data, (uint8_t *)(offset + flash_data->area_address), len);
93 
94 	return 0;
95 }
96 
flash_ra_erase(const struct device * dev,off_t offset,size_t len)97 static int flash_ra_erase(const struct device *dev, off_t offset, size_t len)
98 {
99 	struct flash_hp_ra_data *flash_data = dev->data;
100 	struct flash_hp_ra_controller *dev_ctrl = flash_data->controller;
101 	static struct flash_pages_info page_info_off, page_info_len;
102 	fsp_err_t err;
103 	uint32_t block_num;
104 	int rc, rc2;
105 	int key = 0;
106 	bool is_contain_end_block = false;
107 
108 	if (!flash_ra_valid_range(flash_data, offset, len)) {
109 		return -EINVAL;
110 	}
111 
112 	if (!len) {
113 		return 0;
114 	}
115 
116 	LOG_DBG("flash: erase 0x%lx, len: %u", (long)(offset + flash_data->area_address), len);
117 
118 	rc = flash_get_page_info_by_offs(dev, offset, &page_info_off);
119 
120 	if (rc != 0) {
121 		return -EINVAL;
122 	}
123 
124 	if (offset != page_info_off.start_offset) {
125 		return -EINVAL;
126 	}
127 
128 	if (flash_data->FlashRegion == CODE_FLASH) {
129 #if defined(CONFIG_DUAL_BANK_MODE)
130 		if ((offset + len) == (uint32_t)FLASH_HP_CF_DUAL_HIGH_END_ADDRESS) {
131 			page_info_len.index = FLASH_HP_CF_BLOCK_32KB_DUAL_HIGH_END + 1;
132 			is_contain_end_block = true;
133 		}
134 #else
135 		if ((offset + len) == (uint32_t)DT_REG_SIZE(DT_NODELABEL(flash0))) {
136 			page_info_len.index = FLASH_HP_CF_BLOCK_32KB_LINEAR_END + 1;
137 			is_contain_end_block = true;
138 		}
139 #endif
140 	} else {
141 		if ((offset + len) == (uint32_t)DT_REG_SIZE(DT_NODELABEL(flash1))) {
142 			page_info_len.index = FLASH_HP_DF_BLOCK_END;
143 			is_contain_end_block = true;
144 		}
145 	}
146 
147 	if (!is_contain_end_block) {
148 		rc2 = flash_get_page_info_by_offs(dev, (offset + len), &page_info_len);
149 		if (rc2 != 0) {
150 			return -EINVAL;
151 		}
152 		if ((offset + len) != (page_info_len.start_offset)) {
153 			return -EIO;
154 		}
155 	}
156 
157 	block_num = (uint32_t)((page_info_len.index) - page_info_off.index);
158 
159 	if (block_num > 0) {
160 		if (flash_data->FlashRegion == CODE_FLASH) {
161 			/* Disable interrupts during code flash operations */
162 			key = irq_lock();
163 		} else {
164 			k_sem_take(&dev_ctrl->ctrl_sem, K_FOREVER);
165 		}
166 
167 		err = R_FLASH_HP_Erase(&dev_ctrl->flash_ctrl,
168 				       (long)(flash_data->area_address + offset), block_num);
169 
170 		if (err != FSP_SUCCESS) {
171 			if (flash_data->FlashRegion == CODE_FLASH) {
172 				irq_unlock(key);
173 			} else {
174 				k_sem_give(&dev_ctrl->ctrl_sem);
175 			}
176 			return -EIO;
177 		}
178 
179 		if (flash_data->FlashRegion == DATA_FLASH) {
180 			/* Wait for the erase complete event flag, if BGO is SET  */
181 			if (true == dev_ctrl->fsp_config.data_flash_bgo) {
182 				while (!g_event_flash.erase_complete) {
183 					k_sleep(K_USEC(10));
184 				}
185 				g_event_flash.erase_complete = false;
186 			}
187 		}
188 
189 		if (flash_data->FlashRegion == CODE_FLASH) {
190 			irq_unlock(key);
191 		} else {
192 			k_sem_give(&dev_ctrl->ctrl_sem);
193 		}
194 	}
195 
196 	return 0;
197 }
198 
flash_ra_write(const struct device * dev,off_t offset,const void * data,size_t len)199 static int flash_ra_write(const struct device *dev, off_t offset, const void *data, size_t len)
200 {
201 	fsp_err_t err;
202 	struct flash_hp_ra_data *flash_data = dev->data;
203 	struct flash_hp_ra_controller *dev_ctrl = flash_data->controller;
204 	int key = 0;
205 
206 	if (!flash_ra_valid_range(flash_data, offset, len)) {
207 		return -EINVAL;
208 	}
209 
210 	if (!len) {
211 		return 0;
212 	}
213 
214 	LOG_DBG("flash: write 0x%lx, len: %u", (long)(offset + flash_data->area_address), len);
215 
216 	if (flash_data->FlashRegion == CODE_FLASH) {
217 		/* Disable interrupts during code flash operations */
218 		key = irq_lock();
219 	} else {
220 		k_sem_take(&dev_ctrl->ctrl_sem, K_FOREVER);
221 	}
222 
223 	err = R_FLASH_HP_Write(&dev_ctrl->flash_ctrl, (uint32_t)data,
224 			       (long)(offset + flash_data->area_address), len);
225 
226 	if (err != FSP_SUCCESS) {
227 		if (flash_data->FlashRegion == CODE_FLASH) {
228 			irq_unlock(key);
229 		} else {
230 			k_sem_give(&dev_ctrl->ctrl_sem);
231 		}
232 		return -EIO;
233 	}
234 
235 	if (flash_data->FlashRegion == DATA_FLASH) {
236 		/* Wait for the write complete event flag, if BGO is SET  */
237 		if (true == dev_ctrl->fsp_config.data_flash_bgo) {
238 			while (!g_event_flash.write_complete) {
239 				k_sleep(K_USEC(10));
240 			}
241 			g_event_flash.write_complete = false;
242 		}
243 	}
244 
245 	if (flash_data->FlashRegion == CODE_FLASH) {
246 		irq_unlock(key);
247 	} else {
248 		k_sem_give(&dev_ctrl->ctrl_sem);
249 	}
250 
251 	return 0;
252 }
253 
flash_ra_get_size(const struct device * dev,uint64_t * size)254 static int flash_ra_get_size(const struct device *dev, uint64_t *size)
255 {
256 	struct flash_hp_ra_data *flash_data = dev->data;
257 	*size = (uint64_t)flash_data->area_size;
258 
259 	return 0;
260 }
261 
262 #ifdef CONFIG_FLASH_PAGE_LAYOUT
flash_ra_page_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)263 void flash_ra_page_layout(const struct device *dev, const struct flash_pages_layout **layout,
264 			  size_t *layout_size)
265 {
266 	struct flash_hp_ra_data *flash_data = dev->data;
267 
268 	if (flash_data->FlashRegion == DATA_FLASH) {
269 		flash_ra_layout[0].pages_count = flash_data->area_size / FLASH_HP_DF_BLOCK_SIZE;
270 		flash_ra_layout[0].pages_size = FLASH_HP_DF_BLOCK_SIZE;
271 
272 		*layout_size = 1;
273 	} else {
274 #if defined(CONFIG_DUAL_BANK_MODE)
275 		flash_ra_layout[0].pages_count =
276 			(FLASH_HP_CF_BLOCK_8KB_LOW_END - FLASH_HP_CF_BLOCK_8KB_LOW_START) + 1;
277 		flash_ra_layout[0].pages_size = FLASH_HP_CF_BLOCK_8KB_SIZE;
278 
279 		flash_ra_layout[1].pages_count = (FLASH_HP_CF_BLOCK_32KB_DUAL_LOW_END -
280 						  FLASH_HP_CF_BLOCK_32KB_DUAL_LOW_START) +
281 						 1;
282 		flash_ra_layout[1].pages_size = FLASH_HP_CF_BLOCK_32KB_SIZE;
283 
284 		flash_ra_layout[2].pages_count = FLASH_HP_CF_NUM_BLOCK_RESERVED;
285 		flash_ra_layout[2].pages_size =
286 			(FLASH_HP_BANK2_OFFSET -
287 			 (flash_ra_layout[0].pages_count * flash_ra_layout[0].pages_size) -
288 			 (flash_ra_layout[1].pages_count * flash_ra_layout[1].pages_size)) /
289 			FLASH_HP_CF_NUM_BLOCK_RESERVED;
290 
291 		flash_ra_layout[3].pages_count =
292 			(FLASH_HP_CF_BLOCK_8KB_HIGH_END - FLASH_HP_CF_BLOCK_8KB_HIGH_START) + 1;
293 		flash_ra_layout[3].pages_size = FLASH_HP_CF_BLOCK_8KB_SIZE;
294 
295 		/* The final block is the dummy block */
296 		flash_ra_layout[4].pages_count = (FLASH_HP_CF_BLOCK_32KB_DUAL_HIGH_END + 1 -
297 						  FLASH_HP_CF_BLOCK_32KB_DUAL_HIGH_START) +
298 						 1;
299 		flash_ra_layout[4].pages_size = FLASH_HP_CF_BLOCK_32KB_SIZE;
300 
301 		*layout_size = 5;
302 #else
303 		flash_ra_layout[0].pages_count =
304 			(FLASH_HP_CF_BLOCK_8KB_LOW_END - FLASH_HP_CF_BLOCK_8KB_LOW_START) + 1;
305 		flash_ra_layout[0].pages_size = FLASH_HP_CF_BLOCK_8KB_SIZE;
306 		flash_ra_layout[1].pages_count =
307 			(FLASH_HP_CF_BLOCK_32KB_LINEAR_END - FLASH_HP_CF_BLOCK_32KB_LINEAR_START) +
308 			1;
309 		flash_ra_layout[1].pages_size = FLASH_HP_CF_BLOCK_32KB_SIZE;
310 
311 		*layout_size = 2;
312 #endif
313 	}
314 
315 	*layout = flash_ra_layout;
316 }
317 #endif
318 
flash_ra_get_parameters(const struct device * dev)319 static const struct flash_parameters *flash_ra_get_parameters(const struct device *dev)
320 {
321 	const struct flash_hp_ra_config *config = dev->config;
322 
323 	return &config->flash_ra_parameters;
324 }
325 
326 static struct flash_hp_ra_controller flash_hp_ra_controller = {
327 	.fsp_config = {
328 		.data_flash_bgo = true,
329 		.p_callback = bgo_callback,
330 		.p_context = NULL,
331 		.irq = (IRQn_Type)DT_INST_IRQ_BY_NAME(0, frdyi, irq),
332 		.err_irq = (IRQn_Type)DT_INST_IRQ_BY_NAME(0, fiferr, irq),
333 		.err_ipl = DT_INST_IRQ_BY_NAME(0, fiferr, priority),
334 		.ipl = DT_INST_IRQ_BY_NAME(0, frdyi, priority),
335 	}};
336 
337 #ifdef CONFIG_FLASH_EX_OP_ENABLED
flash_ra_ex_op(const struct device * dev,uint16_t code,const uintptr_t in,void * out)338 static int flash_ra_ex_op(const struct device *dev, uint16_t code, const uintptr_t in, void *out)
339 {
340 	int err = -ENOTSUP;
341 
342 	switch (code) {
343 #if defined(CONFIG_FLASH_RA_WRITE_PROTECT)
344 	case FLASH_RA_EX_OP_WRITE_PROTECT:
345 		err = flash_ra_ex_op_write_protect(dev, in, out);
346 		break;
347 #endif /* CONFIG_FLASH_RA_WRITE_PROTECT */
348 
349 	default:
350 		break;
351 	}
352 
353 	return err;
354 }
355 #endif
356 
flash_ra_init(const struct device * dev)357 static int flash_ra_init(const struct device *dev)
358 {
359 	const struct device *dev_ctrl = DEVICE_DT_INST_GET(0);
360 	struct flash_hp_ra_data *flash_data = dev->data;
361 
362 	if (!device_is_ready(dev_ctrl)) {
363 		return -ENODEV;
364 	}
365 
366 	if (flash_data->area_address == FLASH_HP_DF_START) {
367 		flash_data->FlashRegion = DATA_FLASH;
368 	} else {
369 		flash_data->FlashRegion = CODE_FLASH;
370 	}
371 
372 	flash_data->controller = dev_ctrl->data;
373 
374 	return 0;
375 }
376 
flash_controller_ra_irq_config_func(const struct device * dev)377 static void flash_controller_ra_irq_config_func(const struct device *dev)
378 {
379 	ARG_UNUSED(dev);
380 
381 	R_ICU->IELSR[DT_IRQ_BY_NAME(DT_DRV_INST(0), frdyi, irq)] =
382 		BSP_PRV_IELS_ENUM(EVENT_FCU_FRDYI);
383 	R_ICU->IELSR[DT_IRQ_BY_NAME(DT_DRV_INST(0), fiferr, irq)] =
384 		BSP_PRV_IELS_ENUM(EVENT_FCU_FIFERR);
385 
386 	IRQ_CONNECT(DT_IRQ_BY_NAME(DT_DRV_INST(0), frdyi, irq),
387 		    DT_IRQ_BY_NAME(DT_DRV_INST(0), frdyi, priority), fcu_frdyi_isr,
388 		    DEVICE_DT_INST_GET(0), 0);
389 	IRQ_CONNECT(DT_IRQ_BY_NAME(DT_DRV_INST(0), fiferr, irq),
390 		    DT_IRQ_BY_NAME(DT_DRV_INST(0), fiferr, priority), fcu_fiferr_isr,
391 		    DEVICE_DT_INST_GET(0), 0);
392 
393 	irq_enable(DT_INST_IRQ_BY_NAME(0, frdyi, irq));
394 	irq_enable(DT_INST_IRQ_BY_NAME(0, fiferr, irq));
395 }
396 
flash_controller_ra_init(const struct device * dev)397 static int flash_controller_ra_init(const struct device *dev)
398 {
399 	fsp_err_t err;
400 	const struct flash_hp_ra_controller_config *cfg = dev->config;
401 	struct flash_hp_ra_controller *data = dev->data;
402 
403 	cfg->irq_config(dev);
404 
405 	err = R_FLASH_HP_Open(&data->flash_ctrl, &data->fsp_config);
406 
407 	if (err != FSP_SUCCESS) {
408 		LOG_DBG("flash: open error=%d", (int)err);
409 		return -EIO;
410 	}
411 
412 	k_sem_init(&data->ctrl_sem, 1, 1);
413 
414 	return 0;
415 }
416 
417 static struct flash_hp_ra_controller_config flash_hp_ra_controller_config = {
418 	.irq_config = flash_controller_ra_irq_config_func,
419 };
420 
421 static DEVICE_API(flash, flash_ra_api) = {
422 	.erase = flash_ra_erase,
423 	.write = flash_ra_write,
424 	.read = flash_ra_read,
425 	.get_parameters = flash_ra_get_parameters,
426 	.get_size = flash_ra_get_size,
427 #ifdef CONFIG_FLASH_PAGE_LAYOUT
428 	.page_layout = flash_ra_page_layout,
429 #endif
430 #ifdef CONFIG_FLASH_EX_OP_ENABLED
431 	.ex_op = flash_ra_ex_op,
432 #endif
433 };
434 
435 #define RA_FLASH_INIT(index)                                                                       \
436 	struct flash_hp_ra_data flash_hp_ra_data_##index = {.area_address = DT_REG_ADDR(index),    \
437 							    .area_size = DT_REG_SIZE(index)};      \
438 	static struct flash_hp_ra_config flash_hp_ra_config_##index = {                            \
439 		.flash_ra_parameters = {                                                           \
440 			.write_block_size = GET_SIZE(                                              \
441 				(CHECK_EQ(DT_REG_ADDR(index), FLASH_HP_DF_START)), 4, 128),        \
442 			.erase_value = 0xff,                                                       \
443 		}};                                                                                \
444                                                                                                    \
445 	DEVICE_DT_DEFINE(index, flash_ra_init, NULL, &flash_hp_ra_data_##index,                    \
446 			 &flash_hp_ra_config_##index, POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY,     \
447 			 &flash_ra_api);
448 
449 DT_FOREACH_CHILD_STATUS_OKAY(DT_DRV_INST(0), RA_FLASH_INIT);
450 
451 /* define the flash controller device just to run the init. */
452 DEVICE_DT_DEFINE(DT_DRV_INST(0), flash_controller_ra_init, NULL, &flash_hp_ra_controller,
453 		 &flash_hp_ra_controller_config, PRE_KERNEL_1, CONFIG_FLASH_INIT_PRIORITY, NULL);
454