blob: 652ddf46ab965c01a833bccd0f95e31141598b4a [file] [log] [blame] [edit]
/*
* 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++;
}
}
}