1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7
8 #include <errno.h>
9
10 #include <zephyr/drivers/flash.h>
11 #include <zephyr/logging/log.h>
12 #include <string.h>
13
14 LOG_MODULE_REGISTER(flash, CONFIG_FLASH_LOG_LEVEL);
15
z_impl_flash_fill(const struct device * dev,uint8_t val,off_t offset,size_t size)16 int z_impl_flash_fill(const struct device *dev, uint8_t val, off_t offset,
17 size_t size)
18 {
19 uint8_t filler[CONFIG_FLASH_FILL_BUFFER_SIZE];
20 const struct flash_driver_api *api =
21 (const struct flash_driver_api *)dev->api;
22 const struct flash_parameters *fparams = api->get_parameters(dev);
23 int rc = 0;
24 size_t stored = 0;
25
26 if (sizeof(filler) < fparams->write_block_size) {
27 LOG_ERR("Size of CONFIG_FLASH_FILL_BUFFER_SIZE");
28 return -EINVAL;
29 }
30 /* The flash_write will, probably, check write alignment but this
31 * is too late, as we write datain chunks; data alignment may be
32 * broken by the size of the last chunk, that is why the check
33 * happens here too.
34 * Note that we have no way to check whether offset and size are
35 * are correct, as such info is only available at the level of
36 * a driver, so only basic check on offset.
37 */
38 if (offset < 0) {
39 LOG_ERR("Negative offset not allowed\n");
40 return -EINVAL;
41 }
42 if ((size | (size_t)offset) & (fparams->write_block_size - 1)) {
43 LOG_ERR("Incorrect size or offset alignment, expected %zx\n",
44 fparams->write_block_size);
45 return -EINVAL;
46 }
47
48 memset(filler, val, sizeof(filler));
49
50 while (stored < size) {
51 size_t chunk = MIN(sizeof(filler), size - stored);
52
53 rc = api->write(dev, offset + stored, filler, chunk);
54 if (rc < 0) {
55 LOG_DBG("Fill to dev %p failed at offset 0x%zx\n",
56 dev, (size_t)offset + stored);
57 break;
58 }
59 stored += chunk;
60 }
61 return rc;
62 }
63
z_impl_flash_flatten(const struct device * dev,off_t offset,size_t size)64 int z_impl_flash_flatten(const struct device *dev, off_t offset, size_t size)
65 {
66 const struct flash_driver_api *api =
67 (const struct flash_driver_api *)dev->api;
68 __maybe_unused const struct flash_parameters *params = api->get_parameters(dev);
69
70 #if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE)
71 if ((flash_params_get_erase_cap(params) & FLASH_ERASE_C_EXPLICIT) &&
72 api->erase != NULL) {
73 return api->erase(dev, offset, size);
74 }
75 #endif
76
77 #if defined(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE)
78 return flash_fill(dev, params->erase_value, offset, size);
79 #else
80 return -ENOSYS;
81 #endif
82 }
83