| /* |
| * Copyright (c) 2017 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <errno.h> |
| |
| #include <zephyr/drivers/flash.h> |
| |
| static int flash_get_page_info(const struct device *dev, off_t offs, |
| uint32_t index, struct flash_pages_info *info) |
| { |
| const struct flash_driver_api *api = dev->api; |
| const struct flash_pages_layout *layout; |
| size_t layout_size; |
| uint32_t index_jmp; |
| |
| info->start_offset = 0; |
| info->index = 0U; |
| |
| api->page_layout(dev, &layout, &layout_size); |
| |
| while (layout_size--) { |
| info->size = layout->pages_size; |
| if (offs == 0) { |
| index_jmp = index - info->index; |
| } else { |
| index_jmp = (offs - info->start_offset) / info->size; |
| } |
| |
| index_jmp = MIN(index_jmp, layout->pages_count); |
| info->start_offset += (index_jmp * info->size); |
| info->index += index_jmp; |
| if (index_jmp < layout->pages_count) { |
| return 0; |
| } |
| |
| layout++; |
| } |
| |
| return -EINVAL; /* page at offs or idx doesn't exist */ |
| } |
| |
| int z_impl_flash_get_page_info_by_offs(const struct device *dev, off_t offs, |
| struct flash_pages_info *info) |
| { |
| return flash_get_page_info(dev, offs, 0U, info); |
| } |
| |
| int z_impl_flash_get_page_info_by_idx(const struct device *dev, |
| uint32_t page_index, |
| struct flash_pages_info *info) |
| { |
| return flash_get_page_info(dev, 0, page_index, info); |
| } |
| |
| size_t z_impl_flash_get_page_count(const struct device *dev) |
| { |
| const struct flash_driver_api *api = dev->api; |
| const struct flash_pages_layout *layout; |
| size_t layout_size; |
| size_t count = 0; |
| |
| api->page_layout(dev, &layout, &layout_size); |
| |
| while (layout_size--) { |
| count += layout->pages_count; |
| layout++; |
| } |
| |
| return count; |
| } |
| |
| void flash_page_foreach(const struct device *dev, flash_page_cb cb, |
| void *data) |
| { |
| const struct flash_driver_api *api = dev->api; |
| const struct flash_pages_layout *layout; |
| struct flash_pages_info page_info; |
| size_t block, num_blocks, page = 0, i; |
| off_t off = 0; |
| |
| api->page_layout(dev, &layout, &num_blocks); |
| |
| for (block = 0; block < num_blocks; block++) { |
| const struct flash_pages_layout *l = &layout[block]; |
| page_info.size = l->pages_size; |
| |
| for (i = 0; i < l->pages_count; i++) { |
| page_info.start_offset = off; |
| page_info.index = page; |
| |
| if (!cb(&page_info, data)) { |
| return; |
| } |
| |
| off += page_info.size; |
| page++; |
| } |
| } |
| } |