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