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 
9 #include <string.h>
10 
11 #include "its_flash_nand.h"
12 #include "flash_fs/its_flash_fs.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_nand_init(const struct its_flash_fs_config_t * cfg)36 static psa_status_t its_flash_nand_init(const struct its_flash_fs_config_t *cfg)
37 {
38     int32_t err;
39     struct its_flash_nand_dev_t *flash_dev =
40         (struct its_flash_nand_dev_t *)cfg->flash_dev;
41 
42     if (flash_dev->buf_size < cfg->block_size) {
43         return PSA_ERROR_PROGRAMMER_ERROR;
44     }
45 
46     err = flash_dev->driver->Initialize(NULL);
47     if (err != ARM_DRIVER_OK) {
48         return PSA_ERROR_STORAGE_FAILURE;
49     }
50 
51     return PSA_SUCCESS;
52 }
53 
its_flash_nand_read(const struct its_flash_fs_config_t * cfg,uint32_t block_id,uint8_t * buff,size_t offset,size_t size)54 static psa_status_t its_flash_nand_read(const struct its_flash_fs_config_t *cfg,
55                                         uint32_t block_id, uint8_t *buff,
56                                         size_t offset, size_t size)
57 {
58     struct its_flash_nand_dev_t *flash_dev =
59         (struct its_flash_nand_dev_t *)cfg->flash_dev;
60     uint32_t addr;
61     uint32_t remaining_len, read_length = 0;
62     uint32_t aligned_addr;
63     uint32_t item_number;
64 
65     /* The max size of flash data_width is 4 bytes. */
66     uint8_t temp_buffer[sizeof(uint32_t)];
67     ARM_FLASH_CAPABILITIES DriverCapabilities;
68     uint8_t data_width;
69     int ret;
70 
71     if (block_id == ITS_BLOCK_INVALID_ID) {
72         return PSA_ERROR_PROGRAMMER_ERROR;
73     }
74 
75     if (block_id == flash_dev->buf_block_id_0) {
76         (void)memcpy(buff, flash_dev->write_buf_0 + offset, size);
77     } else if (block_id == flash_dev->buf_block_id_1) {
78         (void)memcpy(buff, flash_dev->write_buf_1 + offset, size);
79     } else {
80         addr = get_phys_address(cfg, block_id, offset);
81         remaining_len = size;
82         DriverCapabilities = flash_dev->driver->GetCapabilities();
83         data_width = data_width_byte[DriverCapabilities.data_width];
84 
85         /*
86          * CMSIS ARM_FLASH_ReadData API requires the `addr` data type size
87          * aligned. Data type size is specified by the data_width in
88          * ARM_FLASH_CAPABILITIES.
89          */
90         aligned_addr = (addr / data_width) * data_width;
91 
92         /* Read the first data_width bytes data if `addr` is not aligned. */
93         if (aligned_addr != addr) {
94             ret = flash_dev->driver->ReadData(aligned_addr, temp_buffer, 1);
95             if (ret < 0) {
96                 return PSA_ERROR_STORAGE_FAILURE;
97             }
98 
99             /* Record how many target data have been read. */
100             read_length = ((addr - aligned_addr + size >= data_width) ?
101                                 (data_width - (addr - aligned_addr)) : size);
102             /* Copy the read data. */
103             memcpy(buff, temp_buffer + addr - aligned_addr, read_length);
104             remaining_len -= read_length;
105         }
106 
107         /*
108          * The `cnt` parameter in CMSIS ARM_FLASH_ReadData indicates number of
109          * data items to read.
110          */
111         if (remaining_len) {
112             item_number = remaining_len / data_width;
113             if (item_number) {
114                 ret = flash_dev->driver->ReadData(addr + read_length,
115                                                   (uint8_t *)buff + read_length,
116                                                   item_number);
117                 if (ret < 0) {
118                     return PSA_ERROR_STORAGE_FAILURE;
119                 }
120                 read_length += item_number * data_width;
121                 remaining_len -= item_number * data_width;
122             }
123         }
124 
125         /* Read the last data item if there is still remaing data. */
126         if (remaining_len) {
127             ret = flash_dev->driver->ReadData(addr + read_length,
128                                               temp_buffer, 1);
129             if (ret < 0) {
130                 return PSA_ERROR_STORAGE_FAILURE;
131             }
132             /* Copy the read data. */
133             memcpy(buff + read_length, temp_buffer, remaining_len);
134         }
135     }
136 
137     return PSA_SUCCESS;
138 }
139 
its_flash_nand_write(const struct its_flash_fs_config_t * cfg,uint32_t block_id,const uint8_t * buff,size_t offset,size_t size)140 static psa_status_t its_flash_nand_write(
141                                     const struct its_flash_fs_config_t *cfg,
142                                     uint32_t block_id, const uint8_t *buff,
143                                     size_t offset, size_t size)
144 {
145     struct its_flash_nand_dev_t *flash_dev =
146         (struct its_flash_nand_dev_t *)cfg->flash_dev;
147 
148     if (block_id == ITS_BLOCK_INVALID_ID) {
149         return PSA_ERROR_PROGRAMMER_ERROR;
150     }
151 
152     /* Write to the match block buffer if exists. Otherwise use the empty
153      * buffer if exists. If no more empty buffer, return error.
154      */
155     if (block_id == flash_dev->buf_block_id_0) {
156         (void)memcpy(flash_dev->write_buf_0 + offset, buff, size);
157     } else if (block_id == flash_dev->buf_block_id_1) {
158         (void)memcpy(flash_dev->write_buf_1 + offset, buff, size);
159     } else if (flash_dev->buf_block_id_0 == ITS_BLOCK_INVALID_ID) {
160         flash_dev->buf_block_id_0 = block_id;
161         (void)memcpy(flash_dev->write_buf_0 + offset, buff, size);
162     } else if (flash_dev->buf_block_id_1 == ITS_BLOCK_INVALID_ID) {
163         flash_dev->buf_block_id_1 = block_id;
164         (void)memcpy(flash_dev->write_buf_1 + offset, buff, size);
165     } else {
166         return PSA_ERROR_PROGRAMMER_ERROR;
167     }
168 
169     return PSA_SUCCESS;
170 }
171 
its_flash_nand_flush(const struct its_flash_fs_config_t * cfg,uint32_t block_id)172 static psa_status_t its_flash_nand_flush(
173                                     const struct its_flash_fs_config_t *cfg,
174                                     uint32_t block_id)
175 {
176     int32_t err;
177     struct its_flash_nand_dev_t *flash_dev =
178         (struct its_flash_nand_dev_t *)cfg->flash_dev;
179     uint32_t addr;
180     ARM_FLASH_CAPABILITIES DriverCapabilities;
181     uint8_t data_width;
182 
183     DriverCapabilities = flash_dev->driver->GetCapabilities();
184     data_width = data_width_byte[DriverCapabilities.data_width];
185     if (block_id == flash_dev->buf_block_id_0) {
186         addr = get_phys_address(cfg, flash_dev->buf_block_id_0, 0);
187 
188         /*
189          * Flush the buffered write data to flash. For NAND flash,
190          * cfg->block_size should always be a multiplier of data_width.
191          */
192         err = flash_dev->driver->ProgramData(addr, flash_dev->write_buf_0,
193                                              cfg->block_size / data_width);
194         if (err < 0) {
195             return PSA_ERROR_STORAGE_FAILURE;
196         }
197 
198         /* Clear the write buffer */
199         (void)memset(flash_dev->write_buf_0, 0, flash_dev->buf_size);
200         flash_dev->buf_block_id_0 = ITS_BLOCK_INVALID_ID;
201     } else if (block_id == flash_dev->buf_block_id_1) {
202         addr = get_phys_address(cfg, flash_dev->buf_block_id_1, 0);
203 
204         /* Flush the buffered write data to flash*/
205         err = flash_dev->driver->ProgramData(addr, flash_dev->write_buf_1,
206                                              cfg->block_size / data_width);
207         if (err < 0) {
208             return PSA_ERROR_STORAGE_FAILURE;
209         }
210 
211         /* Clear the write buffer */
212         (void)memset(flash_dev->write_buf_1, 0, flash_dev->buf_size);
213         flash_dev->buf_block_id_1 = ITS_BLOCK_INVALID_ID;
214     } else {
215         return PSA_ERROR_GENERIC_ERROR;
216     }
217 
218     return PSA_SUCCESS;
219 }
220 
its_flash_nand_erase(const struct its_flash_fs_config_t * cfg,uint32_t block_id)221 static psa_status_t its_flash_nand_erase(const struct its_flash_fs_config_t *cfg,
222                                          uint32_t block_id)
223 {
224     int32_t err;
225     uint32_t addr;
226     size_t offset;
227     struct its_flash_nand_dev_t *flash_dev =
228         (struct its_flash_nand_dev_t *)cfg->flash_dev;
229 
230     for (offset = 0; offset < cfg->block_size; offset += cfg->sector_size) {
231         addr = get_phys_address(cfg, block_id, offset);
232 
233         err = flash_dev->driver->EraseSector(addr);
234         if (err != ARM_DRIVER_OK) {
235             return PSA_ERROR_STORAGE_FAILURE;
236         }
237     }
238 
239     return PSA_SUCCESS;
240 }
241 
242 const struct its_flash_fs_ops_t its_flash_fs_ops_nand = {
243     .init = its_flash_nand_init,
244     .read = its_flash_nand_read,
245     .write = its_flash_nand_write,
246     .flush = its_flash_nand_flush,
247     .erase = its_flash_nand_erase,
248 };
249