1 /*
2  *
3  * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  */
8 
9 #include "spi_strataflashj3_flash_lib.h"
10 #include "cfi_drv.h"
11 
12 
13 #define MAX_PROGRAM_SIZE                128 /* should be less than page size */
14 #define MAX_READ_SIZE                   MAX_PROGRAM_SIZE /* should be less than
15                                                           * page size
16                                                           */
17 #define MANUFACTURER_ID                 0x89
18 #define DEVICE_CODE                     0x18
19 #define ERASE_BLOCK_SIZE                256
20 #define FLASH_END_ADDRESS_8MB           0x00800000
21 #define FLASH_SECTOR_ERASE_SIZE         0x4000
22 
23 #define BUFFER_SIZE (MAX_PROGRAM_SIZE + 8) /* Need a bit overhead for
24                                             * the commands
25                                             */
26 
27 uint8_t send_buf_strata[BUFFER_SIZE];
28 
cfi_strataflashj3_erase_chip(struct cfi_strataflashj3_dev_t * dev)29 enum strataflashj3_error_t cfi_strataflashj3_erase_chip(
30                                         struct cfi_strataflashj3_dev_t* dev)
31 {
32     enum strataflashj3_error_t ret;
33     uint32_t base_addr = dev->controller->cfg->base;
34     if (!dev->is_initialized) {
35         CFI_FLASH_LOG_MSG("%s: not initialized\n\r", __func__);
36         return STRATAFLASHJ3_ERR_NOT_INITIALIZED;
37     }
38     CFI_FLASH_LOG_MSG("%s\n\r", __func__);
39     for(uint32_t counter = 0;
40         counter < FLASH_END_ADDRESS_8MB;
41         counter += FLASH_SECTOR_ERASE_SIZE)
42     {
43         ret = nor_erase(base_addr+counter);
44         if (ret != STRATAFLASHJ3_ERR_NONE) {
45             return ret;
46         }
47     }
48 
49     return STRATAFLASHJ3_ERR_NONE;
50 }
51 
erase_block(struct cfi_strataflashj3_dev_t * dev,uint32_t addr)52 enum strataflashj3_error_t erase_block(struct cfi_strataflashj3_dev_t* dev,
53                                        uint32_t addr)
54 {
55   uint32_t base_addr = dev->controller->cfg->base;
56   enum strataflashj3_error_t ret;
57 
58   for(int counter = 0;counter<ERASE_BLOCK_SIZE;counter++){
59     ret = nor_byte_program(base_addr+addr+counter,0xFF);
60     if (ret != STRATAFLASHJ3_ERR_NONE) {
61         return ret;
62     }
63   }
64   return STRATAFLASHJ3_ERR_NONE;
65 }
66 
cfi_strataflashj3_erase(struct cfi_strataflashj3_dev_t * dev,uint32_t addr)67 enum strataflashj3_error_t cfi_strataflashj3_erase(
68                                         struct cfi_strataflashj3_dev_t* dev,
69                                         uint32_t addr)
70 {
71     enum strataflashj3_error_t ret;
72 
73     if (!dev->is_initialized) {
74         CFI_FLASH_LOG_MSG("%s: not initialized\n\r", __func__);
75         return STRATAFLASHJ3_ERR_NOT_INITIALIZED;
76     }
77     CFI_FLASH_LOG_MSG("%s: addr=0x%x\n\r", __func__, addr);
78     ret = erase_block(dev,addr);
79     if (ret != STRATAFLASHJ3_ERR_NONE) {
80         return ret;
81     }
82 
83     return STRATAFLASHJ3_ERR_NONE;
84 }
85 
cfi_strataflashj3_program_data_byte(struct cfi_strataflashj3_dev_t * dev,uint32_t addr,const uint8_t * data,uint32_t cnt)86 static enum strataflashj3_error_t cfi_strataflashj3_program_data_byte(
87                                         struct cfi_strataflashj3_dev_t* dev,
88                                         uint32_t addr,
89                                         const uint8_t *data,
90                                         uint32_t cnt)
91 {
92     uint32_t remaining_bytes = cnt;
93     uint32_t current_data_index = 0;
94     uint32_t current_addr = addr;
95     uint32_t write_size;
96     uint32_t base_addr = dev->controller->cfg->base;
97 
98     while (remaining_bytes) {
99 
100         if (remaining_bytes < MAX_PROGRAM_SIZE) {
101             write_size = remaining_bytes;
102         } else {
103             write_size = MAX_PROGRAM_SIZE;
104         }
105         for (int i = 0; i < write_size; i++) {
106             send_buf_strata[i] = data[current_data_index++];
107         }
108         for(int counter = 0; counter < write_size; counter++){
109           nor_byte_program(base_addr + current_addr + (counter),
110                            send_buf_strata[counter]);
111         }
112 
113         remaining_bytes -= write_size;
114         current_addr += write_size;
115     }
116 
117     return STRATAFLASHJ3_ERR_NONE;
118 }
119 
cfi_strataflashj3_program(struct cfi_strataflashj3_dev_t * dev,uint32_t addr,const uint8_t * data,uint32_t cnt)120 enum strataflashj3_error_t cfi_strataflashj3_program(
121                                         struct cfi_strataflashj3_dev_t* dev,
122                                         uint32_t addr,
123                                         const uint8_t *data,
124                                         uint32_t cnt)
125 {
126     enum strataflashj3_error_t ret;
127     uint32_t remaining_space;
128     uint32_t current_addr = addr;
129     uint8_t *current_data_ptr = (uint8_t*)data;
130     uint32_t current_cnt = cnt;
131 
132     if (!dev->is_initialized) {
133         CFI_FLASH_LOG_MSG("%s: not initialized\n\r", __func__);
134         return STRATAFLASHJ3_ERR_NOT_INITIALIZED;
135     }
136     CFI_FLASH_LOG_MSG("%s: addr=0x%x, cnt=%u\n\r", __func__, addr, cnt);
137 
138     /* Is write alligned? */
139     if ((addr % dev->program_unit) != 0) {
140         return STRATAFLASHJ3_ERR_WRONG_ARGUMENT;
141     }
142 
143     /* Check the limits */
144     if ((addr + cnt) > (dev->total_sector_cnt * dev->sector_size)) {
145         return STRATAFLASHJ3_ERR_WRONG_ARGUMENT;
146     }
147 
148     if ((addr % MAX_PROGRAM_SIZE) != 0) {
149         /* unaligned addr */
150         remaining_space = MAX_PROGRAM_SIZE - (addr % MAX_PROGRAM_SIZE);
151         if (cnt > remaining_space) {
152             /* crossing the page boundary */
153             /* first write the unaligned data to make addr aligned*/
154             ret = cfi_strataflashj3_program_data_byte(dev,
155                                                       current_addr,
156                                                       current_data_ptr,
157                                                       remaining_space);
158             if (ret != STRATAFLASHJ3_ERR_NONE) {
159                 return ret;
160             }
161             current_addr += remaining_space;
162             current_data_ptr += remaining_space;
163             current_cnt -= remaining_space;
164         }
165     }
166 
167     ret = cfi_strataflashj3_program_data_byte(dev,
168                                               current_addr,
169                                               current_data_ptr,
170                                               current_cnt);
171 
172     return ret;
173 }
174 
cfi_strataflashj3_read(struct cfi_strataflashj3_dev_t * dev,uint32_t addr,uint8_t * data,uint32_t cnt)175 enum strataflashj3_error_t cfi_strataflashj3_read(
176                                         struct cfi_strataflashj3_dev_t* dev,
177                                         uint32_t addr,
178                                         uint8_t *data, uint32_t cnt)
179 {
180     uint32_t remaining_bytes = cnt;
181     uint32_t current_data_index = 0;
182     uint32_t current_addr = addr;
183     uint32_t read_size;
184     uint32_t base_addr = dev->controller->cfg->base ;
185 
186     if (!dev->is_initialized) {
187         CFI_FLASH_LOG_MSG("%s: not initialized\n\r", __func__);
188         return STRATAFLASHJ3_ERR_NOT_INITIALIZED;
189     }
190     CFI_FLASH_LOG_MSG("%s: addr=0x%x, cnt=%u\n\r", __func__, addr, cnt);
191 
192     /* Check the limits */
193     if(addr == 0xFFFFFFFF){
194 	return STRATAFLASHJ3_ERR_WRONG_ARGUMENT;
195     }
196     if ((addr + cnt) > (dev->total_sector_cnt * dev->sector_size)) {
197         return STRATAFLASHJ3_ERR_WRONG_ARGUMENT;
198     }
199 
200     while (remaining_bytes) {
201 
202         /* prepare send buffer */
203         if (remaining_bytes < MAX_READ_SIZE) {
204             read_size = remaining_bytes;
205         } else {
206             read_size = MAX_READ_SIZE;
207         }
208 
209         /* copy data to user location */
210         for (int counter = 0; counter < read_size; counter++) {
211             data[current_data_index] =
212                     nor_cfi_reg_read(base_addr + current_addr + (counter));
213             current_data_index++;
214         }
215 
216         remaining_bytes -= read_size;
217         current_addr += read_size;
218     }
219 
220     return STRATAFLASHJ3_ERR_NONE;
221 }
222 
cfi_strataflashj3_verify_id(struct cfi_strataflashj3_dev_t * dev)223 static enum strataflashj3_error_t cfi_strataflashj3_verify_id(
224                                 struct cfi_strataflashj3_dev_t* dev)
225 {
226     uint32_t base_addr;
227     uint32_t vendor_id, device_code;
228 
229     base_addr = dev->controller->cfg->base;
230 
231     nor_send_cmd(base_addr, NOR_CMD_READ_ID_CODE);
232     vendor_id = nor_cfi_reg_read(base_addr);
233     device_code = nor_cfi_reg_read(base_addr+4);
234 
235     if(vendor_id != MANUFACTURER_ID || device_code != DEVICE_CODE){
236       CFI_FLASH_LOG_MSG("ID miss-match %X-%X\n\r",
237                               vendor_id, device_code);
238       return STRATAFLASHJ3_ERR_WRONG_MEMORY;
239     }
240 
241     dev->is_initialized = true;
242 
243     CFI_FLASH_LOG_MSG("VENDOR ID: %X \n\r",vendor_id);
244     CFI_FLASH_LOG_MSG("STATUS ID: %X \n\r",device_code);
245 
246     cfi_strataflashj3_erase(dev,0);
247 
248     return STRATAFLASHJ3_ERR_NONE;
249 }
250 
cfi_strataflashj3_initialize(struct cfi_strataflashj3_dev_t * dev)251 enum strataflashj3_error_t cfi_strataflashj3_initialize(
252                                         struct cfi_strataflashj3_dev_t* dev)
253 {
254     if (dev->is_initialized) {
255         CFI_FLASH_LOG_MSG("%s: already initialized\n\r", __func__);
256         return STRATAFLASHJ3_ERR_NONE;
257     }
258 
259     dev->is_initialized = true;
260 
261     CFI_FLASH_LOG_MSG("%s: CFI Flash Lib is initialized.\n\r", __func__);
262 
263     return STRATAFLASHJ3_ERR_NONE;
264 }
265 
cfi_strataflashj3_uninitialize(struct cfi_strataflashj3_dev_t * dev)266 void cfi_strataflashj3_uninitialize(struct cfi_strataflashj3_dev_t* dev)
267 {
268     dev->is_initialized = false;
269 }
270