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