1 /*
2  * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
3  * Copyright (c) 2020, Cypress Semiconductor Corporation. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  */
8 #include <string.h>
9 #include "its_flash_nor.h"
10 
11 #include "flash_fs/its_flash_fs.h"
12 #include "driver/Driver_Flash.h"
13 
14 /* Valid entries for data item width */
15 static const uint32_t data_width_byte[] = {
16     sizeof(uint8_t),
17     sizeof(uint16_t),
18     sizeof(uint32_t),
19 };
20 
21 /**
22  * \brief Gets physical address of the given block ID.
23  *
24  * \param[in] cfg       Flash FS configuration
25  * \param[in] block_id  Block ID
26  * \param[in] offset    Offset position from the init of the block
27  *
28  * \returns Returns physical address for the given block ID.
29  */
get_phys_address(const struct its_flash_fs_config_t * cfg,uint32_t block_id,size_t offset)30 static uint32_t get_phys_address(const struct its_flash_fs_config_t *cfg,
31                                  uint32_t block_id, size_t offset)
32 {
33     return cfg->flash_area_addr + (block_id * cfg->block_size) + offset;
34 }
35 
its_flash_nor_init(const struct its_flash_fs_config_t * cfg)36 static psa_status_t its_flash_nor_init(const struct its_flash_fs_config_t *cfg)
37 {
38     int32_t err;
39 
40     err = ((ARM_DRIVER_FLASH *)cfg->flash_dev)->Initialize(NULL);
41     if (err != ARM_DRIVER_OK) {
42         return PSA_ERROR_STORAGE_FAILURE;
43     }
44 
45     return PSA_SUCCESS;
46 }
47 
flash_read_unaligned(const struct its_flash_fs_config_t * cfg,uint32_t addr,uint8_t * buff,size_t size)48 static psa_status_t flash_read_unaligned(
49                                     const struct its_flash_fs_config_t *cfg,
50                                     uint32_t addr, uint8_t *buff, size_t size)
51 {
52     uint32_t remaining_len, read_length = 0;
53     uint32_t aligned_addr;
54     uint32_t item_number;
55 
56     /* The max size of flash data_width is 4 bytes. */
57     uint8_t temp_buffer[sizeof(uint32_t)];
58     ARM_FLASH_CAPABILITIES DriverCapabilities;
59     uint8_t data_width;
60     int ret;
61 
62     DriverCapabilities =
63                     ((ARM_DRIVER_FLASH *)cfg->flash_dev)->GetCapabilities();
64     data_width = data_width_byte[DriverCapabilities.data_width];
65 
66     /*
67      * CMSIS ARM_FLASH_ReadData API requires the `addr` data type size
68      * aligned. Data type size is specified by the data_width in
69      * ARM_FLASH_CAPABILITIES.
70      */
71     aligned_addr = (addr / data_width) * data_width;
72     remaining_len = size;
73 
74     /* Read the first data_width bytes data if `addr` is not aligned. */
75     if (aligned_addr != addr) {
76         ret = ((ARM_DRIVER_FLASH *)cfg->flash_dev)->ReadData(aligned_addr,
77                                                              temp_buffer, 1);
78         if (ret < 0) {
79             return PSA_ERROR_STORAGE_FAILURE;
80         }
81 
82         /* Record how many target data have been read. */
83         read_length = ((addr - aligned_addr + size >= data_width) ?
84          (data_width - (addr - aligned_addr)) : size);
85 
86         /* Copy the read data. */
87         memcpy(buff, temp_buffer + addr - aligned_addr, read_length);
88         remaining_len -= read_length;
89     }
90 
91     /*
92      * The `cnt` parameter in CMSIS ARM_FLASH_ReadData indicates number of
93      * data items to read.
94      */
95     if (remaining_len) {
96         item_number = remaining_len / data_width;
97         if (item_number) {
98             ret = ((ARM_DRIVER_FLASH *)cfg->flash_dev)->ReadData(
99                                                 addr + read_length,
100                                                 (uint8_t *)buff + read_length,
101                                                 item_number);
102             if (ret < 0) {
103                 return PSA_ERROR_STORAGE_FAILURE;
104             }
105             read_length += item_number * data_width;
106             remaining_len -= item_number * data_width;
107         }
108     }
109 
110     /* Read the last data item if there is still remaing data. */
111     if (remaining_len) {
112         ret = ((ARM_DRIVER_FLASH *)cfg->flash_dev)->ReadData(
113                                                             addr + read_length,
114                                                             temp_buffer, 1);
115         if (ret < 0) {
116             return PSA_ERROR_STORAGE_FAILURE;
117         }
118         /* Copy the read data. */
119         memcpy(buff + read_length, temp_buffer, remaining_len);
120     }
121 
122     return PSA_SUCCESS;
123 }
its_flash_nor_read(const struct its_flash_fs_config_t * cfg,uint32_t block_id,uint8_t * buff,size_t offset,size_t size)124 static psa_status_t its_flash_nor_read(const struct its_flash_fs_config_t *cfg,
125                                        uint32_t block_id, uint8_t *buff,
126                                        size_t offset, size_t size)
127 {
128     uint32_t addr;
129 
130     if (size == 0) {
131         return PSA_SUCCESS;
132     }
133     addr = get_phys_address(cfg, block_id, offset);
134     return flash_read_unaligned(cfg, addr, buff, size);
135 }
136 
its_flash_nor_write(const struct its_flash_fs_config_t * cfg,uint32_t block_id,const uint8_t * buff,size_t offset,size_t size)137 static psa_status_t its_flash_nor_write(const struct its_flash_fs_config_t *cfg,
138                                         uint32_t block_id, const uint8_t *buff,
139                                         size_t offset, size_t size)
140 {
141     int32_t err;
142     ARM_FLASH_CAPABILITIES DriverCapabilities;
143     uint32_t addr;
144     uint8_t data_width;
145 
146     DriverCapabilities =
147                     ((ARM_DRIVER_FLASH *)cfg->flash_dev)->GetCapabilities();
148     data_width = data_width_byte[DriverCapabilities.data_width];
149 
150     addr = get_phys_address(cfg, block_id, offset);
151 
152     err = ((ARM_DRIVER_FLASH *)cfg->flash_dev)->ProgramData(addr, buff,
153                                                         size / data_width);
154     if (err < 0) {
155         return PSA_ERROR_STORAGE_FAILURE;
156     }
157 
158     return PSA_SUCCESS;
159 }
160 
its_flash_nor_flush(const struct its_flash_fs_config_t * cfg,uint32_t block_id)161 static psa_status_t its_flash_nor_flush(const struct its_flash_fs_config_t *cfg,
162                                         uint32_t block_id)
163 {
164     /* Nothing needs to be done for NOR flash, as writes are commited to flash
165      * immediately.
166      */
167     (void)cfg;
168     (void)block_id;
169     return PSA_SUCCESS;
170 }
171 
its_flash_nor_erase(const struct its_flash_fs_config_t * cfg,uint32_t block_id)172 static psa_status_t its_flash_nor_erase(const struct its_flash_fs_config_t *cfg,
173                                         uint32_t block_id)
174 {
175     int32_t err;
176     uint32_t addr;
177     size_t offset;
178 
179     for (offset = 0; offset < cfg->block_size; offset += cfg->sector_size) {
180         addr = get_phys_address(cfg, block_id, offset);
181 
182         err = ((ARM_DRIVER_FLASH *)cfg->flash_dev)->EraseSector(addr);
183         if (err != ARM_DRIVER_OK) {
184             return PSA_ERROR_STORAGE_FAILURE;
185         }
186     }
187 
188     return PSA_SUCCESS;
189 }
190 
191 const struct its_flash_fs_ops_t its_flash_fs_ops_nor = {
192     .init = its_flash_nor_init,
193     .read = its_flash_nor_read,
194     .write = its_flash_nor_write,
195     .flush = its_flash_nor_flush,
196     .erase = its_flash_nor_erase,
197 };
198