1 /*
2  * Copyright (c) 2018-2020 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){ MT25QL_FUNC_STATE_NOT_INITED };
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