1 /*
2 * Copyright (c) 2018-2019 Arm Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdlib.h>
18 /* Use memcpy function */
19 #include <string.h>
20
21 #include "mt25ql_flash_lib.h"
22 #include "qspi_ip6514e_drv.h"
23
24 /** Setter bit manipulation macro */
25 #define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX)))
26 /** Clearing bit manipulation macro */
27 #define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX)))
28 /** Getter bit manipulation macro */
29 #define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX))))
30
31 #define BITS_PER_WORD 32U
32 #define BYTES_PER_WORD 4U
33
34 #define ARG_NOT_USED 0
35 #define ARG_PTR_NOT_USED NULL
36
37 /** MT25QL used command */
38 #define WRITE_ENABLE_CMD 0x06U
39 #define READ_ENHANCED_VOLATILE_CFG_REG_CMD 0x65U
40 #define WRITE_ENHANCED_VOLATILE_CFG_REG_CMD 0x61U
41 #define READ_VOLATILE_CFG_REG_CMD 0x85U
42 #define WRITE_VOLATILE_CFG_REG_CMD 0x81U
43 #define READ_FLAG_STATUS_REG_CMD 0x70U
44 #define SUBSECTOR_ERASE_32KB_CMD 0x52U
45 #define SUBSECTOR_ERASE_4KB_CMD 0x20U
46 #define SECTOR_ERASE_CMD 0xD8U
47 #define BULK_ERASE_CMD 0xC7U
48 /*
49 * The baud rate divisor in \ref mt25ql_dev_t needs to be configured adequately
50 * to handle those commands.
51 */
52 #define QUAD_OUTPUT_FAST_READ_CMD 0x6BU
53 #define FAST_READ_CMD 0x0BU
54 #define READ_CMD 0x03U
55 #define QUAD_INPUT_FAST_PROGRAM_CMD 0x32U
56 #define PAGE_PROGRAM_CMD 0x02U
57
58 /** MT25QL Enhanced Volatile Configuration Register access */
59 #define ENHANCED_VOLATILE_CFG_REG_LEN 1U
60 #define ENHANCED_VOLATILE_CFG_REG_QSPI_POS 7U
61 #define ENHANCED_VOLATILE_CFG_REG_DSPI_POS 6U
62
63 /** MT25QL Volatile Configuration Register access */
64 #define VOLATILE_CFG_REG_LEN 1U
65 #define VOLATILE_CFG_REG_DUMMY_CYCLES_POS 4U
66 #define VOLATILE_CFG_REG_DUMMY_CYCLES_BITS 4U
67
68 /** MT25QL Flag Status Register access */
69 #define FLAG_STATUS_REG_LEN 1U
70 #define FLAG_STATUS_REG_READY_POS 7U
71
72 /*
73 * 10 is the minimal number of dummy clock cycles needed to reach the maximal
74 * frequency of the Quad Output Fast Read Command.
75 */
76 #define QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES 10U
77 #define FAST_READ_DUMMY_CYCLES 8U
78 #define RESET_STATE_DUMMY_CYCLES 8U
79 #define DEFAULT_READ_DUMMY_CYCLES 0U
80 #define QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES 0U
81 #define PAGE_PROGRAM_DUMMY_CYCLES 0U
82
83 /* Only up to 8 bytes can be read or written using the Flash commands. */
84 #define CMD_DATA_MAX_SIZE 8U
85
86 /**
87 * \brief Change specific bits in a 32 bits word.
88 *
89 * \param[in,out] word Pointer of the word to change
90 * \param[in] bits bits_length bits to put at bits_pos in the word
91 * pointed
92 * \param[in] bits_length Number of bits to change
93 * \param[in] bits_pos Position of the bits to change
94 *
95 * \note This function will do nothing if the parameters given are incorrect:
96 * * word is NULL
97 * * bits_length + bits_pos > 32
98 * * bits_length is 0
99 */
change_bits_in_word(volatile uint32_t * word,uint32_t bits,uint32_t bits_length,uint32_t bits_pos)100 static void change_bits_in_word(volatile uint32_t *word,
101 uint32_t bits,
102 uint32_t bits_length,
103 uint32_t bits_pos)
104 {
105 uint32_t mask;
106
107 if ((word == NULL) ||
108 ((bits_length + bits_pos) > BITS_PER_WORD) ||
109 (bits_length == 0U)) {
110 /* Silently fail */
111 return;
112 }
113
114 /* Change all the bits */
115 if (bits_length == BITS_PER_WORD) {
116 *word = bits;
117 return;
118 }
119
120 mask = ((1U << bits_length) - 1);
121 /*
122 * We change the bits in three steps:
123 * - clear bits_length bits with zeroes at bits_pos in the word
124 * - mask bits in case it contains more than bits_length bits
125 * - set the new bits in the cleared word
126 * Because the data pointed by word is only read once, the data will still
127 * be coherent after an interruption that changes it.
128 */
129 *word = ((*word & ~(mask << bits_pos)) | ((bits & mask) << bits_pos));
130 }
131
132 /**
133 * \brief Send the Write Enable command, needed before any write.
134 *
135 * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
136 */
send_write_enable(struct mt25ql_dev_t * dev)137 static void send_write_enable(struct mt25ql_dev_t* dev)
138 {
139 qspi_ip6514e_send_simple_cmd(dev->controller, WRITE_ENABLE_CMD);
140 }
141
142 /**
143 * \brief Set SPI mode on the flash device and on the controller.
144 *
145 * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
146 * \param[in] spi_mode SPI mode to be set on flash device and controller
147 * \ref qspi_ip6514e_spi_mode_t
148 *
149 * \return Return error code as specified in \ref mt25ql_error_t
150 */
set_spi_mode(struct mt25ql_dev_t * dev,enum qspi_ip6514e_spi_mode_t spi_mode)151 static enum mt25ql_error_t set_spi_mode(struct mt25ql_dev_t* dev,
152 enum qspi_ip6514e_spi_mode_t spi_mode)
153 {
154 uint8_t enhanced_volatile_cfg_reg = 0;
155 enum qspi_ip6514e_error_t controller_error;
156
157 /* Read the Enhanced Volatile Configuration Register, modify it according
158 * to the requested SPI mode then write back the modified value to the
159 * register. This will activate the SPI mode on the flash side.
160 */
161 controller_error = qspi_ip6514e_send_read_cmd(
162 dev->controller,
163 READ_ENHANCED_VOLATILE_CFG_REG_CMD,
164 &enhanced_volatile_cfg_reg,
165 ENHANCED_VOLATILE_CFG_REG_LEN,
166 ARG_NOT_USED,
167 ARG_NOT_USED,
168 0); /* No dummy cycles needed for
169 this command. */
170 if (controller_error != QSPI_IP6514E_ERR_NONE) {
171 return (enum mt25ql_error_t)controller_error;
172 }
173
174 switch(spi_mode) {
175 case QSPI_IP6514E_SPI_MODE:
176 /* Disable the Dual- and Quad-SPI modes.
177 * Clearing the bit enables the mode, setting it disables it.
178 */
179 SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
180 SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
181 break;
182 case QSPI_IP6514E_DSPI_MODE:
183 /* Disable the Quad-SPI mode and activate DSPI mode.
184 * Clearing the bit enables the mode, setting it disables it.
185 */
186 CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
187 SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
188 break;
189 case QSPI_IP6514E_QSPI_MODE:
190 /* Disable the Dual-SPI mode and activate QSPI mode.
191 * Clearing the bit enables the mode, setting it disables it.
192 */
193 SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
194 CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
195 break;
196 default:
197 return MT25QL_ERR_WRONG_ARGUMENT;
198 }
199
200 send_write_enable(dev);
201
202 controller_error = qspi_ip6514e_send_write_cmd(
203 dev->controller,
204 WRITE_ENHANCED_VOLATILE_CFG_REG_CMD,
205 &enhanced_volatile_cfg_reg,
206 ENHANCED_VOLATILE_CFG_REG_LEN,
207 ARG_NOT_USED,
208 ARG_NOT_USED,
209 0); /* No dummy cycles needed for
210 this command. */
211 if (controller_error != QSPI_IP6514E_ERR_NONE) {
212 return (enum mt25ql_error_t)controller_error;
213 }
214
215 /* Activate the requested SPI mode on the controller side as well. */
216 controller_error = qspi_ip6514e_set_spi_mode(dev->controller,
217 spi_mode,
218 spi_mode,
219 spi_mode);
220 if (controller_error != QSPI_IP6514E_ERR_NONE) {
221 return (enum mt25ql_error_t)controller_error;
222 }
223
224 return MT25QL_ERR_NONE;
225 }
226
227 /**
228 * \brief Change the number of dummy clock cycles subsequent to all FAST READ
229 * commands.
230 *
231 * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
232 * \param[in] dummy_cycles Dummy clock cycles to set
233 *
234 * \return Return error code as specified in \ref mt25ql_error_t
235 */
change_dummy_cycles(struct mt25ql_dev_t * dev,uint32_t dummy_cycles)236 static enum mt25ql_error_t change_dummy_cycles(struct mt25ql_dev_t* dev,
237 uint32_t dummy_cycles)
238 {
239 uint32_t volatile_cfg_reg = 0;
240 enum qspi_ip6514e_error_t controller_error;
241
242 /*
243 * Changes the number of dummy cycles in the Volatile Configuration
244 * Register.
245 */
246 controller_error = qspi_ip6514e_send_read_cmd(dev->controller,
247 READ_VOLATILE_CFG_REG_CMD,
248 &volatile_cfg_reg,
249 VOLATILE_CFG_REG_LEN,
250 ARG_NOT_USED,
251 ARG_NOT_USED,
252 0); /* No dummy cycles needed
253 for this command. */
254 if (controller_error != QSPI_IP6514E_ERR_NONE) {
255 return (enum mt25ql_error_t)controller_error;
256 }
257
258 change_bits_in_word(&volatile_cfg_reg,
259 dummy_cycles,
260 VOLATILE_CFG_REG_DUMMY_CYCLES_BITS,
261 VOLATILE_CFG_REG_DUMMY_CYCLES_POS);
262
263 send_write_enable(dev);
264
265 controller_error = qspi_ip6514e_send_write_cmd(dev->controller,
266 WRITE_VOLATILE_CFG_REG_CMD,
267 &volatile_cfg_reg,
268 VOLATILE_CFG_REG_LEN,
269 ARG_NOT_USED,
270 ARG_NOT_USED,
271 0); /* No dummy cycles needed
272 for this command. */
273 if (controller_error != QSPI_IP6514E_ERR_NONE) {
274 return (enum mt25ql_error_t)controller_error;
275 }
276
277 return MT25QL_ERR_NONE;
278 }
279
280 /**
281 * \brief Wait until the current program/erase is finished.
282 *
283 * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
284 *
285 * \return Return error code as specified in \ref mt25ql_error_t
286 */
wait_program_or_erase_complete(struct mt25ql_dev_t * dev)287 static enum mt25ql_error_t wait_program_or_erase_complete(
288 struct mt25ql_dev_t* dev)
289 {
290 enum qspi_ip6514e_error_t controller_error;
291 uint8_t flag_status_reg = 0;
292
293 /* Wait until the ready bit of the Flag Status Register is set */
294 while (!GET_BIT(flag_status_reg, FLAG_STATUS_REG_READY_POS)) {
295 controller_error = qspi_ip6514e_send_read_cmd(dev->controller,
296 READ_FLAG_STATUS_REG_CMD,
297 &flag_status_reg,
298 FLAG_STATUS_REG_LEN,
299 ARG_NOT_USED,
300 ARG_NOT_USED,
301 0); /* No dummy cycles
302 needed for this
303 command. */
304 if (controller_error != QSPI_IP6514E_ERR_NONE) {
305 return (enum mt25ql_error_t)controller_error;
306 }
307 }
308
309 return MT25QL_ERR_NONE;
310 }
311
312 /**
313 * \brief Execute a program command that crosses the page size boundary.
314 *
315 * \param[in] dev Pointer to MT25QL device structure
316 * \ref mt25ql_dev_t
317 * \param[in] opcode Opcode for the command.
318 * \param[in] write_data Pointer to a memory zone where the write_len
319 * number of bytes are located to write for this
320 * command.
321 * \param[in] write_len Number of bytes to write for the command.
322 * Between 1 and 8 bytes (both included) can be
323 * written.
324 * \param[in] addr Address used for the command
325 * \param[in] addr_bytes_number Number of address bytes for this command.
326 * If an address is not needed for the command,
327 * use 0 for argument, otherwise between 1 and
328 * 4 bytes (both included) can be used.
329 * \param[in] dummy_cycles Number of dummy cycles required for the
330 * command, between 0 and 31 (both included).
331 *
332 * \return Return error code as specified in \ref mt25ql_error_t
333 *
334 * \note This function will execute two commands: one to program the bytes up to
335 * the page boundary and another one to program the rest. It will wait
336 * that bytes are programmed from first command before triggering the
337 * second one.
338 * \note This function does not send a write enable command before the first
339 * command and does not check that bytes were programmed after the second
340 * command.
341 */
send_boundary_cross_write_cmd(struct mt25ql_dev_t * dev,uint8_t opcode,const void * write_data,uint32_t write_len,uint32_t addr,uint32_t addr_bytes_number,uint32_t dummy_cycles)342 static enum mt25ql_error_t send_boundary_cross_write_cmd(
343 struct mt25ql_dev_t* dev,
344 uint8_t opcode,
345 const void *write_data,
346 uint32_t write_len,
347 uint32_t addr,
348 uint32_t addr_bytes_number,
349 uint32_t dummy_cycles)
350 {
351 enum qspi_ip6514e_error_t controller_error;
352 enum mt25ql_error_t library_error;
353 /*
354 * Remaining bytes between the current address and the end of the current
355 * page.
356 */
357 uint32_t page_remainder = FLASH_PAGE_SIZE - (addr % FLASH_PAGE_SIZE);
358
359 /* First write up to the end of the current page. */
360 controller_error = qspi_ip6514e_send_write_cmd(dev->controller, opcode,
361 write_data, page_remainder,
362 addr, addr_bytes_number,
363 dummy_cycles);
364 if (controller_error != QSPI_IP6514E_ERR_NONE) {
365 return (enum mt25ql_error_t)controller_error;
366 }
367
368 write_data = (void *)((uint32_t)write_data + page_remainder);
369 addr += page_remainder;
370
371 /* Wait for the page to be written before sending new commands. */
372 library_error = wait_program_or_erase_complete(dev);
373 if (library_error != MT25QL_ERR_NONE) {
374 return library_error;
375 }
376
377 /* Then write the remaining data of the write_len bytes. */
378 send_write_enable(dev);
379 controller_error = qspi_ip6514e_send_write_cmd(dev->controller, opcode,
380 write_data,
381 write_len - page_remainder,
382 addr, addr_bytes_number,
383 dummy_cycles);
384 if (controller_error != QSPI_IP6514E_ERR_NONE) {
385 return (enum mt25ql_error_t)controller_error;
386 }
387
388 return MT25QL_ERR_NONE;
389 }
390
mt25ql_config_mode(struct mt25ql_dev_t * dev,enum mt25ql_functional_state_t f_state)391 enum mt25ql_error_t mt25ql_config_mode(struct mt25ql_dev_t* dev,
392 enum mt25ql_functional_state_t f_state)
393 {
394 enum qspi_ip6514e_error_t controller_error;
395 enum mt25ql_error_t library_error;
396
397 switch(f_state) {
398 case MT25QL_FUNC_STATE_DEFAULT:
399 dev->config_state.spi_mode = QSPI_IP6514E_SPI_MODE;
400 dev->config_state.opcode_read = READ_CMD;
401 dev->config_state.dummy_cycles_read = DEFAULT_READ_DUMMY_CYCLES;
402 dev->config_state.opcode_write = PAGE_PROGRAM_CMD;
403 dev->config_state.dummy_cycles_write = PAGE_PROGRAM_DUMMY_CYCLES;
404 break;
405 case MT25QL_FUNC_STATE_FAST:
406 dev->config_state.spi_mode = QSPI_IP6514E_SPI_MODE;
407 dev->config_state.opcode_read = FAST_READ_CMD;
408 dev->config_state.dummy_cycles_read = FAST_READ_DUMMY_CYCLES;
409 dev->config_state.opcode_write = PAGE_PROGRAM_CMD;
410 dev->config_state.dummy_cycles_write = PAGE_PROGRAM_DUMMY_CYCLES;
411 break;
412 case MT25QL_FUNC_STATE_QUAD_FAST:
413 dev->config_state.spi_mode = QSPI_IP6514E_QSPI_MODE;
414 dev->config_state.opcode_read = QUAD_OUTPUT_FAST_READ_CMD;
415 dev->config_state.dummy_cycles_read =
416 QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES;
417 dev->config_state.opcode_write = QUAD_INPUT_FAST_PROGRAM_CMD;
418 dev->config_state.dummy_cycles_write =
419 QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES;
420 break;
421 default:
422 return MT25QL_ERR_WRONG_ARGUMENT;
423 }
424
425 dev->config_state.func_state = f_state;
426
427 /* This function will first set the Flash memory SPI mode and then set
428 * the controller's SPI mode. It will fail if the two sides do not have
429 * the same mode when this function is called.
430 */
431 library_error = set_spi_mode(dev, dev->config_state.spi_mode);
432 if (library_error != MT25QL_ERR_NONE) {
433 return library_error;
434 }
435
436 /* Set the number of dummy cycles for read commands. */
437 library_error = change_dummy_cycles(
438 dev, dev->config_state.dummy_cycles_read);
439 if (library_error != MT25QL_ERR_NONE) {
440 return library_error;
441 }
442
443 /* The rest of the configuration needs the controller to be disabled */
444 while(!qspi_ip6514e_is_idle(dev->controller));
445 qspi_ip6514e_disable(dev->controller);
446
447 /* Set the baud rate divisor as configured in the device structure. */
448 controller_error = qspi_ip6514e_set_baud_rate_div(dev->controller,
449 dev->baud_rate_div);
450 if (controller_error != QSPI_IP6514E_ERR_NONE) {
451 return (enum mt25ql_error_t)controller_error;
452 }
453
454 /* Set opcode and dummy cycles needed for read commands. */
455 controller_error = qspi_ip6514e_cfg_reads(
456 dev->controller, dev->config_state.opcode_read,
457 dev->config_state.dummy_cycles_read);
458 if (controller_error != QSPI_IP6514E_ERR_NONE) {
459 return (enum mt25ql_error_t)controller_error;
460 }
461
462 /* Set opcode and dummy cycles needed for write commands. */
463 controller_error = qspi_ip6514e_cfg_writes(
464 dev->controller, dev->config_state.opcode_write,
465 dev->config_state.dummy_cycles_write);
466 if (controller_error != QSPI_IP6514E_ERR_NONE) {
467 return (enum mt25ql_error_t)controller_error;
468 }
469
470 /* Set Flash memory constants: bytes per page and address bytes. */
471 controller_error = qspi_ip6514e_cfg_page_size(dev->controller,
472 FLASH_PAGE_SIZE);
473 if (controller_error != QSPI_IP6514E_ERR_NONE) {
474 return (enum mt25ql_error_t)controller_error;
475 }
476
477 controller_error = qspi_ip6514e_cfg_addr_bytes(dev->controller,
478 ADDR_BYTES);
479 if (controller_error != QSPI_IP6514E_ERR_NONE) {
480 return (enum mt25ql_error_t)controller_error;
481 }
482
483 qspi_ip6514e_enable(dev->controller);
484
485 return MT25QL_ERR_NONE;
486 }
487
mt25ql_restore_reset_state(struct mt25ql_dev_t * dev)488 enum mt25ql_error_t mt25ql_restore_reset_state(struct mt25ql_dev_t* dev)
489 {
490 enum mt25ql_error_t library_error;
491
492 /*
493 * This function will first change the Flash memory mode to single SPI and
494 * then change the controller to single SPI. It will fail if the two sides
495 * do not have the same mode when this function is called.
496 */
497 library_error = set_spi_mode(dev, QSPI_IP6514E_SPI_MODE);
498 if (library_error != MT25QL_ERR_NONE) {
499 return library_error;
500 }
501
502 /* Set the default number of dummy cycles for direct read commands. */
503 library_error = change_dummy_cycles(dev, RESET_STATE_DUMMY_CYCLES);
504 if (library_error != MT25QL_ERR_NONE) {
505 return library_error;
506 }
507
508 /* The rest of the configuration needs the controller to be disabled */
509 while(!qspi_ip6514e_is_idle(dev->controller));
510 qspi_ip6514e_disable(dev->controller);
511
512 /* Restore the default value of the QSPI controller registers. */
513 qspi_ip6514e_reset_regs(dev->controller);
514
515 qspi_ip6514e_enable(dev->controller);
516
517 dev->config_state = (struct mt25ql_config_state_t){ 0 };
518 dev->config_state.func_state = MT25QL_FUNC_STATE_NOT_INITED;
519
520 return MT25QL_ERR_NONE;
521 }
522
mt25ql_direct_read(struct mt25ql_dev_t * dev,uint32_t addr,void * data,uint32_t len)523 enum mt25ql_error_t mt25ql_direct_read(struct mt25ql_dev_t* dev,
524 uint32_t addr,
525 void *data,
526 uint32_t len)
527 {
528 /*
529 * The direct access window size is the size of the memory that can be
530 * accessed with a direct access.
531 */
532 uint32_t direct_access_window_size = dev->controller->cfg->addr_mask + 1;
533 /*
534 * The window number is the number of times it will be needed to remap the
535 * address with the remap register. We move this Direct Access window first
536 * window_number times starting at the beginning address to read full
537 * windows of direct_access_window_size bytes. Then we read the remainder
538 * bytes.
539 */
540 uint32_t window_number = len / direct_access_window_size;
541
542 if (data == NULL || len == 0) {
543 return MT25QL_ERR_WRONG_ARGUMENT;
544 }
545
546 if ((addr + len) >= dev->size) {
547 return MT25QL_ERR_ADDR_TOO_BIG;
548 }
549
550 /*
551 * There is no limitation reading through a Flash page boundary hence we
552 * do not add the same logic here than in the write function.
553 */
554
555 /* Transfer the bytes for the window_number windows first. */
556 for (uint32_t window = 0; window < window_number; window++) {
557 qspi_ip6514e_remap_addr(dev->controller, addr);
558
559 /*
560 * The AHB address to access the Flash memory does not change but it
561 * will be translated differently thanks to the remap function.
562 */
563 memcpy(data,
564 (void *)dev->direct_access_start_addr,
565 direct_access_window_size);
566
567 len -= direct_access_window_size;
568 data = (void *)((uint32_t)data + direct_access_window_size);
569 addr += direct_access_window_size;
570 }
571
572 if (len) {
573 /* Transfer the reminder bytes */
574 qspi_ip6514e_remap_addr(dev->controller, addr);
575
576 memcpy(data, (void *)dev->direct_access_start_addr, len);
577 }
578
579 /* Disable remapping for direct accesses outside of this function. */
580 qspi_ip6514e_disable_remap(dev->controller);
581
582 return MT25QL_ERR_NONE;
583 }
584
mt25ql_direct_write(struct mt25ql_dev_t * dev,uint32_t addr,const void * data,uint32_t len)585 enum mt25ql_error_t mt25ql_direct_write(struct mt25ql_dev_t* dev,
586 uint32_t addr,
587 const void *data,
588 uint32_t len)
589 {
590 enum mt25ql_error_t library_error;
591 /*
592 * The direct access window size is the size of the memory that can be
593 * accessed with a direct access.
594 */
595 uint32_t direct_access_window_size = dev->controller->cfg->addr_mask + 1;
596 uint32_t window_number;
597 /* Offset between address and the previous 32 bits aligned word */
598 uint32_t word_offset;
599
600 if (data == NULL || len == 0) {
601 return MT25QL_ERR_WRONG_ARGUMENT;
602 }
603
604 if ((addr + len) >= dev->size) {
605 return MT25QL_ERR_ADDR_TOO_BIG;
606 }
607
608 /*
609 * If the remapping address is not aligned on a 32 bits boundary, a direct
610 * access of one word could cross a Flash page boundary. If that happens,
611 * the bytes of that word that are over the page boundary will instead be
612 * written at the beginning of the same page.
613 * To counter this problem, we align the remapping address and add the word
614 * offset to the address of the direct access for the first window only.
615 */
616 word_offset = addr % BYTES_PER_WORD;
617 /* Make address aligned on a 32 bits alignment. */
618 addr -= word_offset;
619 /*
620 * Only direct_access_window_size address locations are available by direct
621 * access. We calculate the number of windows that we will need to transfer
622 * len bytes. We have to add in the window the offset that we add in the
623 * beginning.
624 */
625 window_number = (len + word_offset) / direct_access_window_size;
626
627 /*
628 * This function assumes that the flash has already been erased.
629 * Transfer the bytes for the window_number windows first.
630 */
631 for (uint32_t window = 0; window < window_number; window++) {
632 /* The controller needs to be disabled while remapping is done. */
633 qspi_ip6514e_remap_addr(dev->controller, addr);
634
635 /*
636 * The AHB address to access the Flash memory does not change but it
637 * will be translated differently thanks to the remap function.
638 */
639 memcpy((void *)(dev->direct_access_start_addr + word_offset),
640 data,
641 direct_access_window_size - word_offset);
642
643 len -= (direct_access_window_size - word_offset);
644 data = (void *)((uint32_t)data +
645 (direct_access_window_size - word_offset));
646 addr += direct_access_window_size;
647
648 /*
649 * The address is now aligned, there is no need to add an offset for the
650 * remaining windows.
651 */
652 word_offset = 0;
653
654 /*
655 * Wait until the last program operation is complete before changing
656 * the remap address.
657 */
658 library_error = wait_program_or_erase_complete(dev);
659 if (library_error != MT25QL_ERR_NONE) {
660 return library_error;
661 }
662 }
663
664 if (len) {
665 /* Transfer the reminder bytes */
666 qspi_ip6514e_remap_addr(dev->controller, addr);
667
668 memcpy((void *)(dev->direct_access_start_addr + word_offset),
669 data,
670 len);
671
672 /* Wait until the last program operation is complete */
673 library_error = wait_program_or_erase_complete(dev);
674 if (library_error != MT25QL_ERR_NONE) {
675 return library_error;
676 }
677 }
678
679 /*
680 * Disable the default remap address for direct accesses outside of this
681 * function.
682 */
683 qspi_ip6514e_disable_remap(dev->controller);
684
685 return MT25QL_ERR_NONE;
686 }
687
mt25ql_command_read(struct mt25ql_dev_t * dev,uint32_t addr,void * data,uint32_t len)688 enum mt25ql_error_t mt25ql_command_read(struct mt25ql_dev_t* dev,
689 uint32_t addr,
690 void *data,
691 uint32_t len)
692 {
693 /* With one single command only 8 bytes can be read. */
694 uint32_t cmd_number = len / CMD_DATA_MAX_SIZE;
695 enum qspi_ip6514e_error_t controller_error;
696
697 if (dev->config_state.func_state == MT25QL_FUNC_STATE_NOT_INITED) {
698 return MT25QL_ERR_NOT_INITED;
699 }
700
701 for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) {
702 controller_error = qspi_ip6514e_send_read_cmd(
703 dev->controller,
704 dev->config_state.opcode_read,
705 data, CMD_DATA_MAX_SIZE, addr,
706 ADDR_BYTES,
707 dev->config_state.dummy_cycles_read);
708 if (controller_error != QSPI_IP6514E_ERR_NONE) {
709 return (enum mt25ql_error_t)controller_error;
710 }
711
712 data = (void *)((uint32_t)data + CMD_DATA_MAX_SIZE);
713 addr += CMD_DATA_MAX_SIZE;
714 len -= CMD_DATA_MAX_SIZE;
715 }
716
717 if (len) {
718 /* Read the remainder. */
719 controller_error = qspi_ip6514e_send_read_cmd(
720 dev->controller,
721 dev->config_state.opcode_read,
722 data, len, addr, ADDR_BYTES,
723 dev->config_state.dummy_cycles_read);
724 if (controller_error != QSPI_IP6514E_ERR_NONE) {
725 return (enum mt25ql_error_t)controller_error;
726 }
727 }
728
729 return MT25QL_ERR_NONE;
730
731 }
732
mt25ql_command_write(struct mt25ql_dev_t * dev,uint32_t addr,const void * data,uint32_t len)733 enum mt25ql_error_t mt25ql_command_write(struct mt25ql_dev_t* dev,
734 uint32_t addr,
735 const void *data,
736 uint32_t len)
737 {
738 /* With one single command only 8 bytes can be written. */
739 uint32_t cmd_number = len / CMD_DATA_MAX_SIZE;
740 enum qspi_ip6514e_error_t controller_error;
741 enum mt25ql_error_t library_error;
742
743 if (dev->config_state.func_state == MT25QL_FUNC_STATE_NOT_INITED) {
744 return MT25QL_ERR_NOT_INITED;
745 }
746
747 for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) {
748 send_write_enable(dev);
749
750 /*
751 * Check if this command is not writing over a page boundary: first and
752 * last bytes are in the same page.
753 */
754 if ((addr / FLASH_PAGE_SIZE) !=
755 ((addr + CMD_DATA_MAX_SIZE - 1) / FLASH_PAGE_SIZE)) {
756 /* The CMD_DATA_MAX_SIZE bytes written are crossing the boundary. */
757 library_error = send_boundary_cross_write_cmd(
758 dev, dev->config_state.opcode_write,
759 data, CMD_DATA_MAX_SIZE, addr,
760 ADDR_BYTES,
761 dev->config_state.dummy_cycles_write);
762 if (library_error != MT25QL_ERR_NONE) {
763 return library_error;
764 }
765 } else {
766 /* Normal case: not crossing the boundary. */
767 controller_error = qspi_ip6514e_send_write_cmd(
768 dev->controller,
769 dev->config_state.opcode_write,
770 data, CMD_DATA_MAX_SIZE, addr,
771 ADDR_BYTES,
772 dev->config_state.dummy_cycles_write);
773 if (controller_error != QSPI_IP6514E_ERR_NONE) {
774 return (enum mt25ql_error_t)controller_error;
775 }
776 }
777
778 /* Wait until the write operation is complete. */
779 library_error = wait_program_or_erase_complete(dev);
780 if (library_error != MT25QL_ERR_NONE) {
781 return library_error;
782 }
783
784 data = (void *)((uint32_t)data + CMD_DATA_MAX_SIZE);
785 addr += CMD_DATA_MAX_SIZE;
786 len -= CMD_DATA_MAX_SIZE;
787 }
788
789 if (len) {
790 /* Write the remainder. */
791 send_write_enable(dev);
792 /*
793 * Check if this command is not writing over a page boundary: first and
794 * last bytes are in the same page.
795 */
796 if ((addr / FLASH_PAGE_SIZE) != ((addr + len - 1) / FLASH_PAGE_SIZE)) {
797 /* The CMD_DATA_MAX_SIZE bytes written are crossing the boundary. */
798 library_error = send_boundary_cross_write_cmd(
799 dev, dev->config_state.opcode_write,
800 data, len, addr, ADDR_BYTES,
801 dev->config_state.dummy_cycles_write);
802 if (library_error != MT25QL_ERR_NONE) {
803 return library_error;
804 }
805 } else {
806 /* Normal case: not crossing the boundary. */
807 controller_error = qspi_ip6514e_send_write_cmd(
808 dev->controller,
809 dev->config_state.opcode_write,
810 data, len, addr, ADDR_BYTES,
811 dev->config_state.dummy_cycles_write);
812 if (controller_error != QSPI_IP6514E_ERR_NONE) {
813 return (enum mt25ql_error_t)controller_error;
814 }
815 }
816
817 /* Wait until the write operation is complete. */
818 library_error = wait_program_or_erase_complete(dev);
819 if (library_error != MT25QL_ERR_NONE) {
820 return library_error;
821 }
822 }
823
824 return MT25QL_ERR_NONE;
825
826 }
827
mt25ql_erase(struct mt25ql_dev_t * dev,uint32_t addr,enum mt25ql_erase_t erase_type)828 enum mt25ql_error_t mt25ql_erase(struct mt25ql_dev_t* dev,
829 uint32_t addr,
830 enum mt25ql_erase_t erase_type)
831 {
832 enum qspi_ip6514e_error_t controller_error;
833 enum mt25ql_error_t library_error;
834 uint8_t erase_cmd;
835 uint32_t addr_bytes;
836
837 if (dev->config_state.func_state == MT25QL_FUNC_STATE_NOT_INITED) {
838 return MT25QL_ERR_NOT_INITED;
839 }
840
841 send_write_enable(dev);
842
843 switch (erase_type) {
844 case MT25QL_ERASE_ALL_FLASH:
845 if (addr != 0) {
846 return MT25QL_ERR_ADDR_NOT_ALIGNED;
847 }
848 erase_cmd = BULK_ERASE_CMD;
849 addr_bytes = ARG_NOT_USED;
850 break;
851 case MT25QL_ERASE_SECTOR_64K:
852 erase_cmd = SECTOR_ERASE_CMD;
853 addr_bytes = ADDR_BYTES;
854 if ((addr % SECTOR_64KB) != 0) {
855 return MT25QL_ERR_ADDR_NOT_ALIGNED;
856 }
857 break;
858 case MT25QL_ERASE_SUBSECTOR_32K:
859 erase_cmd = SUBSECTOR_ERASE_32KB_CMD;
860 addr_bytes = ADDR_BYTES;
861 if ((addr % SUBSECTOR_32KB) != 0) {
862 return MT25QL_ERR_ADDR_NOT_ALIGNED;
863 }
864 break;
865 case MT25QL_ERASE_SUBSECTOR_4K:
866 erase_cmd = SUBSECTOR_ERASE_4KB_CMD;
867 addr_bytes = ADDR_BYTES;
868 if ((addr % SUBSECTOR_4KB) != 0) {
869 return MT25QL_ERR_ADDR_NOT_ALIGNED;
870 }
871 break;
872 default:
873 return MT25QL_ERR_WRONG_ARGUMENT;
874 }
875
876 if (addr >= dev->size) {
877 return MT25QL_ERR_ADDR_TOO_BIG;
878 }
879
880 controller_error = qspi_ip6514e_send_cmd(dev->controller,
881 erase_cmd,
882 ARG_PTR_NOT_USED,
883 ARG_NOT_USED,
884 ARG_PTR_NOT_USED,
885 ARG_NOT_USED,
886 addr,
887 addr_bytes,
888 0); /* No dummy cycles needed for
889 any erase command. */
890 if (controller_error != QSPI_IP6514E_ERR_NONE) {
891 return (enum mt25ql_error_t)controller_error;
892 }
893
894 /* Wait until the erase operation is complete */
895 library_error = wait_program_or_erase_complete(dev);
896 if (library_error != MT25QL_ERR_NONE) {
897 return (enum mt25ql_error_t)controller_error;
898 }
899
900 return MT25QL_ERR_NONE;
901 }
902