1 /*
2  * Copyright (c) 2017 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <drivers/flash.h>
8 
flash_get_page_info(const struct device * dev,off_t offs,uint32_t index,struct flash_pages_info * info)9 static int flash_get_page_info(const struct device *dev, off_t offs,
10 			       uint32_t index, struct flash_pages_info *info)
11 {
12 	const struct flash_driver_api *api = dev->api;
13 	const struct flash_pages_layout *layout;
14 	size_t layout_size;
15 	uint32_t index_jmp;
16 
17 	info->start_offset = 0;
18 	info->index = 0U;
19 
20 	api->page_layout(dev, &layout, &layout_size);
21 
22 	while (layout_size--) {
23 		info->size = layout->pages_size;
24 		if (offs == 0) {
25 			index_jmp = index - info->index;
26 		} else {
27 			index_jmp = (offs - info->start_offset) / info->size;
28 		}
29 
30 		index_jmp = MIN(index_jmp, layout->pages_count);
31 		info->start_offset += (index_jmp * info->size);
32 		info->index += index_jmp;
33 		if (index_jmp < layout->pages_count) {
34 			return 0;
35 		}
36 
37 		layout++;
38 	}
39 
40 	return -EINVAL; /* page at offs or idx doesn't exist */
41 }
42 
z_impl_flash_get_page_info_by_offs(const struct device * dev,off_t offs,struct flash_pages_info * info)43 int z_impl_flash_get_page_info_by_offs(const struct device *dev, off_t offs,
44 				       struct flash_pages_info *info)
45 {
46 	return flash_get_page_info(dev, offs, 0U, info);
47 }
48 
z_impl_flash_get_page_info_by_idx(const struct device * dev,uint32_t page_index,struct flash_pages_info * info)49 int z_impl_flash_get_page_info_by_idx(const struct device *dev,
50 				      uint32_t page_index,
51 				      struct flash_pages_info *info)
52 {
53 	return flash_get_page_info(dev, 0, page_index, info);
54 }
55 
z_impl_flash_get_page_count(const struct device * dev)56 size_t z_impl_flash_get_page_count(const struct device *dev)
57 {
58 	const struct flash_driver_api *api = dev->api;
59 	const struct flash_pages_layout *layout;
60 	size_t layout_size;
61 	size_t count = 0;
62 
63 	api->page_layout(dev, &layout, &layout_size);
64 
65 	while (layout_size--) {
66 		count += layout->pages_count;
67 		layout++;
68 	}
69 
70 	return count;
71 }
72 
flash_page_foreach(const struct device * dev,flash_page_cb cb,void * data)73 void flash_page_foreach(const struct device *dev, flash_page_cb cb,
74 			void *data)
75 {
76 	const struct flash_driver_api *api = dev->api;
77 	const struct flash_pages_layout *layout;
78 	struct flash_pages_info page_info;
79 	size_t block, num_blocks, page = 0, i;
80 	off_t off = 0;
81 
82 	api->page_layout(dev, &layout, &num_blocks);
83 
84 	for (block = 0; block < num_blocks; block++) {
85 		const struct flash_pages_layout *l = &layout[block];
86 		page_info.size = l->pages_size;
87 
88 		for (i = 0; i < l->pages_count; i++) {
89 			page_info.start_offset = off;
90 			page_info.index = page;
91 
92 			if (!cb(&page_info, data)) {
93 				return;
94 			}
95 
96 			off += page_info.size;
97 			page++;
98 		}
99 	}
100 }
101