1 /***************************************************************************
2 * Copyright (C) 2014 by Mahavir Jain <mjain@marvell.com> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
19 ***************************************************************************/
22 * This is QSPI flash controller driver for Marvell's Wireless
23 * Microcontroller platform.
25 * For more information please refer,
26 * https://origin-www.marvell.com/microcontrollers/wi-fi-microcontroller-platform/
35 #include <helper/binarybuffer.h>
36 #include <target/algorithm.h>
37 #include <target/armv7m.h>
39 #define QSPI_R_EN (0x0)
40 #define QSPI_W_EN (0x1)
41 #define QSPI_SS_DISABLE (0x0)
42 #define QSPI_SS_ENABLE (0x1)
43 #define WRITE_DISBALE (0x0)
44 #define WRITE_ENABLE (0x1)
46 #define QSPI_TIMEOUT (1000)
47 #define FIFO_FLUSH_TIMEOUT (1000)
48 #define BLOCK_ERASE_TIMEOUT (1000)
49 #define CHIP_ERASE_TIMEOUT (10000)
51 #define SS_EN (1 << 0)
52 #define XFER_RDY (1 << 1)
53 #define RFIFO_EMPTY (1 << 4)
54 #define WFIFO_EMPTY (1 << 6)
55 #define WFIFO_FULL (1 << 7)
56 #define FIFO_FLUSH (1 << 9)
57 #define RW_EN (1 << 13)
58 #define XFER_STOP (1 << 14)
59 #define XFER_START (1 << 15)
60 #define CONF_MASK (0x7)
61 #define CONF_OFFSET (10)
63 #define INS_WRITE_ENABLE 0x06
64 #define INS_WRITE_DISABLE 0x04
65 #define INS_READ_STATUS 0x05
66 #define INS_PAGE_PROGRAM 0x02
68 #define CNTL 0x0 /* QSPI_BASE + 0x0 */
78 struct mrvlqspi_flash_bank
{
82 const struct flash_device
*dev
;
85 static inline uint32_t mrvlqspi_get_reg(struct flash_bank
*bank
, uint32_t reg
)
87 struct mrvlqspi_flash_bank
*mrvlqspi_info
= bank
->driver_priv
;
88 return reg
+ mrvlqspi_info
->reg_base
;
91 static inline int mrvlqspi_set_din_cnt(struct flash_bank
*bank
, uint32_t count
)
93 struct target
*target
= bank
->target
;
95 return target_write_u32(target
, mrvlqspi_get_reg(bank
, DINCNT
), count
);
98 static inline int mrvlqspi_set_addr(struct flash_bank
*bank
, uint32_t addr
)
100 struct target
*target
= bank
->target
;
102 return target_write_u32(target
, mrvlqspi_get_reg(bank
, ADDR
), addr
);
105 static inline int mrvlqspi_set_instr(struct flash_bank
*bank
, uint32_t instr
)
107 struct target
*target
= bank
->target
;
109 return target_write_u32(target
, mrvlqspi_get_reg(bank
, INSTR
), instr
);
112 static inline int mrvlqspi_set_hdr_cnt(struct flash_bank
*bank
, uint32_t hdr_cnt
)
114 struct target
*target
= bank
->target
;
116 return target_write_u32(target
, mrvlqspi_get_reg(bank
, HDRCNT
), hdr_cnt
);
119 static int mrvlqspi_set_conf(struct flash_bank
*bank
, uint32_t conf_val
)
123 struct target
*target
= bank
->target
;
125 retval
= target_read_u32(target
,
126 mrvlqspi_get_reg(bank
, CONF
), ®val
);
127 if (retval
!= ERROR_OK
)
130 regval
&= ~(CONF_MASK
<< CONF_OFFSET
);
131 regval
|= (conf_val
<< CONF_OFFSET
);
133 return target_write_u32(target
,
134 mrvlqspi_get_reg(bank
, CONF
), regval
);
137 static int mrvlqspi_set_ss_state(struct flash_bank
*bank
, bool state
, int timeout
)
141 struct target
*target
= bank
->target
;
143 retval
= target_read_u32(target
,
144 mrvlqspi_get_reg(bank
, CNTL
), ®val
);
145 if (retval
!= ERROR_OK
)
153 retval
= target_write_u32(target
,
154 mrvlqspi_get_reg(bank
, CNTL
), regval
);
155 if (retval
!= ERROR_OK
)
158 /* wait for xfer_ready to set */
160 retval
= target_read_u32(target
,
161 mrvlqspi_get_reg(bank
, CNTL
), ®val
);
162 if (retval
!= ERROR_OK
)
164 LOG_DEBUG("status: 0x%x", regval
);
165 if ((regval
& XFER_RDY
) == XFER_RDY
)
167 if (timeout
-- <= 0) {
168 LOG_ERROR("timed out waiting for flash");
176 static int mrvlqspi_start_transfer(struct flash_bank
*bank
, bool rw_mode
)
180 struct target
*target
= bank
->target
;
182 retval
= mrvlqspi_set_ss_state(bank
, QSPI_SS_ENABLE
, QSPI_TIMEOUT
);
183 if (retval
!= ERROR_OK
)
186 retval
= target_read_u32(target
,
187 mrvlqspi_get_reg(bank
, CONF
), ®val
);
188 if (retval
!= ERROR_OK
)
196 regval
|= XFER_START
;
198 retval
= target_write_u32(target
,
199 mrvlqspi_get_reg(bank
, CONF
), regval
);
200 if (retval
!= ERROR_OK
)
206 static int mrvlqspi_stop_transfer(struct flash_bank
*bank
)
210 struct target
*target
= bank
->target
;
211 int timeout
= QSPI_TIMEOUT
;
213 /* wait for xfer_ready and wfifo_empty to set */
215 retval
= target_read_u32(target
,
216 mrvlqspi_get_reg(bank
, CNTL
), ®val
);
217 if (retval
!= ERROR_OK
)
219 LOG_DEBUG("status: 0x%x", regval
);
220 if ((regval
& (XFER_RDY
| WFIFO_EMPTY
)) ==
221 (XFER_RDY
| WFIFO_EMPTY
))
223 if (timeout
-- <= 0) {
224 LOG_ERROR("timed out waiting for flash");
230 retval
= target_read_u32(target
,
231 mrvlqspi_get_reg(bank
, CONF
), ®val
);
232 if (retval
!= ERROR_OK
)
237 retval
= target_write_u32(target
,
238 mrvlqspi_get_reg(bank
, CONF
), regval
);
239 if (retval
!= ERROR_OK
)
242 /* wait for xfer_start to reset */
244 retval
= target_read_u32(target
,
245 mrvlqspi_get_reg(bank
, CONF
), ®val
);
246 if (retval
!= ERROR_OK
)
248 LOG_DEBUG("status: 0x%x", regval
);
249 if ((regval
& XFER_START
) == 0)
251 if (timeout
-- <= 0) {
252 LOG_ERROR("timed out waiting for flash");
258 retval
= mrvlqspi_set_ss_state(bank
, QSPI_SS_DISABLE
, QSPI_TIMEOUT
);
259 if (retval
!= ERROR_OK
)
265 static int mrvlqspi_fifo_flush(struct flash_bank
*bank
, int timeout
)
269 struct target
*target
= bank
->target
;
271 retval
= target_read_u32(target
,
272 mrvlqspi_get_reg(bank
, CONF
), &val
);
273 if (retval
!= ERROR_OK
)
278 retval
= target_write_u32(target
,
279 mrvlqspi_get_reg(bank
, CONF
), val
);
280 if (retval
!= ERROR_OK
)
283 /* wait for fifo_flush to clear */
285 retval
= target_read_u32(target
,
286 mrvlqspi_get_reg(bank
, CONF
), &val
);
287 if (retval
!= ERROR_OK
)
289 LOG_DEBUG("status: 0x%x", val
);
290 if ((val
& FIFO_FLUSH
) == 0)
292 if (timeout
-- <= 0) {
293 LOG_ERROR("timed out waiting for flash");
301 static int mrvlqspi_read_byte(struct flash_bank
*bank
, uint8_t *data
)
305 struct target
*target
= bank
->target
;
307 /* wait for rfifo_empty to reset */
309 retval
= target_read_u32(target
,
310 mrvlqspi_get_reg(bank
, CNTL
), &val
);
311 if (retval
!= ERROR_OK
)
313 LOG_DEBUG("status: 0x%x", val
);
314 if ((val
& RFIFO_EMPTY
) == 0)
319 retval
= target_read_u32(target
,
320 mrvlqspi_get_reg(bank
, DIN
), &val
);
321 if (retval
!= ERROR_OK
)
329 static int mrvlqspi_flash_busy_status(struct flash_bank
*bank
, int timeout
)
334 /* Flush read/write fifo's */
335 retval
= mrvlqspi_fifo_flush(bank
, FIFO_FLUSH_TIMEOUT
);
336 if (retval
!= ERROR_OK
)
339 /* Set instruction/addr count value */
340 retval
= mrvlqspi_set_hdr_cnt(bank
, 0x1);
341 if (retval
!= ERROR_OK
)
344 /* Read flash status register in continuous manner */
345 retval
= mrvlqspi_set_din_cnt(bank
, 0x0);
346 if (retval
!= ERROR_OK
)
349 /* Set instruction */
350 retval
= mrvlqspi_set_instr(bank
, INS_READ_STATUS
);
351 if (retval
!= ERROR_OK
)
354 /* Set data and addr pin length */
355 retval
= mrvlqspi_set_conf(bank
, 0x0);
356 if (retval
!= ERROR_OK
)
359 /* Enable read mode transfer */
360 retval
= mrvlqspi_start_transfer(bank
, QSPI_R_EN
);
361 if (retval
!= ERROR_OK
)
365 retval
= mrvlqspi_read_byte(bank
, &val
);
366 if (retval
!= ERROR_OK
)
370 if (timeout
-- <= 0) {
371 LOG_ERROR("timed out waiting for flash");
377 return mrvlqspi_stop_transfer(bank
);
380 static int mrvlqspi_set_write_status(struct flash_bank
*bank
, bool mode
)
385 /* Flush read/write fifo's */
386 retval
= mrvlqspi_fifo_flush(bank
, FIFO_FLUSH_TIMEOUT
);
387 if (retval
!= ERROR_OK
)
390 /* Set instruction/addr count value */
391 retval
= mrvlqspi_set_hdr_cnt(bank
, 0x1);
392 if (retval
!= ERROR_OK
)
396 instr
= INS_WRITE_ENABLE
;
398 instr
= INS_WRITE_DISABLE
;
400 /* Set instruction */
401 retval
= mrvlqspi_set_instr(bank
, instr
);
402 if (retval
!= ERROR_OK
)
405 retval
= mrvlqspi_start_transfer(bank
, QSPI_W_EN
);
406 if (retval
!= ERROR_OK
)
409 retval
= mrvlqspi_stop_transfer(bank
);
410 if (retval
!= ERROR_OK
)
416 static int mrvlqspi_read_id(struct flash_bank
*bank
, uint32_t *id
)
418 uint8_t id_buf
[3] = {0, 0, 0};
421 LOG_DEBUG("Getting ID");
423 /* Flush read/write fifo's */
424 retval
= mrvlqspi_fifo_flush(bank
, FIFO_FLUSH_TIMEOUT
);
425 if (retval
!= ERROR_OK
)
428 /* Set instruction/addr count value */
429 retval
= mrvlqspi_set_hdr_cnt(bank
, 0x1);
430 if (retval
!= ERROR_OK
)
433 /* Set count for number of bytes to read */
434 retval
= mrvlqspi_set_din_cnt(bank
, 0x3);
435 if (retval
!= ERROR_OK
)
438 /* Set instruction */
439 retval
= mrvlqspi_set_instr(bank
, SPIFLASH_READ_ID
);
440 if (retval
!= ERROR_OK
)
443 /* Set data and addr pin length */
444 retval
= mrvlqspi_set_conf(bank
, 0x0);
445 if (retval
!= ERROR_OK
)
448 retval
= mrvlqspi_start_transfer(bank
, QSPI_R_EN
);
449 if (retval
!= ERROR_OK
)
452 for (i
= 0; i
< 3; i
++) {
453 retval
= mrvlqspi_read_byte(bank
, &id_buf
[i
]);
454 if (retval
!= ERROR_OK
)
458 LOG_DEBUG("ID is 0x%x 0x%x 0x%x", id_buf
[0], id_buf
[1], id_buf
[2]);
459 retval
= mrvlqspi_set_ss_state(bank
, QSPI_SS_DISABLE
, QSPI_TIMEOUT
);
460 if (retval
!= ERROR_OK
)
463 *id
= id_buf
[2] << 16 | id_buf
[1] << 8 | id_buf
[0];
467 static int mrvlqspi_block_erase(struct flash_bank
*bank
, uint32_t offset
)
470 struct mrvlqspi_flash_bank
*mrvlqspi_info
= bank
->driver_priv
;
472 /* Set flash write enable */
473 retval
= mrvlqspi_set_write_status(bank
, WRITE_ENABLE
);
474 if (retval
!= ERROR_OK
)
477 /* Set instruction/addr count value */
478 retval
= mrvlqspi_set_hdr_cnt(bank
, (0x1 | (0x3 << 4)));
479 if (retval
!= ERROR_OK
)
482 /* Set read offset address */
483 retval
= mrvlqspi_set_addr(bank
, offset
);
484 if (retval
!= ERROR_OK
)
487 /* Set instruction */
488 retval
= mrvlqspi_set_instr(bank
, mrvlqspi_info
->dev
->erase_cmd
);
489 if (retval
!= ERROR_OK
)
492 retval
= mrvlqspi_start_transfer(bank
, QSPI_W_EN
);
493 if (retval
!= ERROR_OK
)
496 retval
= mrvlqspi_stop_transfer(bank
);
497 if (retval
!= ERROR_OK
)
500 return mrvlqspi_flash_busy_status(bank
, BLOCK_ERASE_TIMEOUT
);
503 static int mrvlqspi_bulk_erase(struct flash_bank
*bank
)
506 struct mrvlqspi_flash_bank
*mrvlqspi_info
= bank
->driver_priv
;
508 /* Set flash write enable */
509 retval
= mrvlqspi_set_write_status(bank
, WRITE_ENABLE
);
510 if (retval
!= ERROR_OK
)
513 /* Set instruction */
514 retval
= mrvlqspi_set_instr(bank
, mrvlqspi_info
->dev
->chip_erase_cmd
);
515 if (retval
!= ERROR_OK
)
518 retval
= mrvlqspi_start_transfer(bank
, QSPI_W_EN
);
519 if (retval
!= ERROR_OK
)
522 retval
= mrvlqspi_stop_transfer(bank
);
523 if (retval
!= ERROR_OK
)
526 return mrvlqspi_flash_busy_status(bank
, CHIP_ERASE_TIMEOUT
);
529 static int mrvlqspi_flash_erase(struct flash_bank
*bank
, int first
, int last
)
531 struct target
*target
= bank
->target
;
532 struct mrvlqspi_flash_bank
*mrvlqspi_info
= bank
->driver_priv
;
533 int retval
= ERROR_OK
;
536 LOG_DEBUG("erase from sector %d to sector %d", first
, last
);
538 if (target
->state
!= TARGET_HALTED
) {
539 LOG_ERROR("Target not halted");
540 return ERROR_TARGET_NOT_HALTED
;
543 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
)) {
544 LOG_ERROR("Flash sector invalid");
545 return ERROR_FLASH_SECTOR_INVALID
;
548 if (!(mrvlqspi_info
->probed
)) {
549 LOG_ERROR("Flash bank not probed");
550 return ERROR_FLASH_BANK_NOT_PROBED
;
553 for (sector
= first
; sector
<= last
; sector
++) {
554 if (bank
->sectors
[sector
].is_protected
) {
555 LOG_ERROR("Flash sector %d protected", sector
);
560 /* If we're erasing the entire chip and the flash supports
561 * it, use a bulk erase instead of going sector-by-sector. */
562 if (first
== 0 && last
== (bank
->num_sectors
- 1)
563 && mrvlqspi_info
->dev
->chip_erase_cmd
!=
564 mrvlqspi_info
->dev
->erase_cmd
) {
565 LOG_DEBUG("Chip supports the bulk erase command."\
566 " Will use bulk erase instead of sector-by-sector erase.");
567 retval
= mrvlqspi_bulk_erase(bank
);
568 if (retval
== ERROR_OK
) {
571 LOG_WARNING("Bulk flash erase failed."
572 " Falling back to sector-by-sector erase.");
575 for (sector
= first
; sector
<= last
; sector
++) {
576 retval
= mrvlqspi_block_erase(bank
,
577 sector
* mrvlqspi_info
->dev
->sectorsize
);
578 if (retval
!= ERROR_OK
)
585 static int mrvlqspi_flash_write(struct flash_bank
*bank
, const uint8_t *buffer
,
586 uint32_t offset
, uint32_t count
)
588 struct target
*target
= bank
->target
;
589 struct mrvlqspi_flash_bank
*mrvlqspi_info
= bank
->driver_priv
;
590 int retval
= ERROR_OK
;
591 uint32_t page_size
, fifo_size
;
592 struct working_area
*fifo
;
593 struct reg_param reg_params
[6];
594 struct armv7m_algorithm armv7m_info
;
595 struct working_area
*write_algorithm
;
598 LOG_DEBUG("offset=0x%08" PRIx32
" count=0x%08" PRIx32
,
601 if (target
->state
!= TARGET_HALTED
) {
602 LOG_ERROR("Target not halted");
603 return ERROR_TARGET_NOT_HALTED
;
606 if (offset
+ count
> mrvlqspi_info
->dev
->size_in_bytes
) {
607 LOG_WARNING("Writes past end of flash. Extra data discarded.");
608 count
= mrvlqspi_info
->dev
->size_in_bytes
- offset
;
611 /* Check sector protection */
612 for (sector
= 0; sector
< bank
->num_sectors
; sector
++) {
613 /* Start offset in or before this sector? */
614 /* End offset in or behind this sector? */
616 (bank
->sectors
[sector
].offset
+ bank
->sectors
[sector
].size
))
617 && ((offset
+ count
- 1) >= bank
->sectors
[sector
].offset
)
618 && bank
->sectors
[sector
].is_protected
) {
619 LOG_ERROR("Flash sector %d protected", sector
);
624 page_size
= mrvlqspi_info
->dev
->pagesize
;
626 /* See contrib/loaders/flash/mrvlqspi.S for src */
627 static const uint8_t mrvlqspi_flash_write_code
[] = {
628 0x4f, 0xf0, 0x00, 0x0a, 0xa2, 0x44, 0x92, 0x45,
629 0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6b, 0xf8,
630 0x5f, 0xf0, 0x01, 0x08, 0xc5, 0xf8, 0x1c, 0x80,
631 0x5f, 0xf0, 0x06, 0x08, 0xc5, 0xf8, 0x10, 0x80,
632 0x5f, 0xf0, 0x01, 0x09, 0x00, 0xf0, 0x6b, 0xf8,
633 0x00, 0xf0, 0x7d, 0xf8, 0x5f, 0xf0, 0x31, 0x08,
634 0xc5, 0xf8, 0x1c, 0x80, 0x90, 0x46, 0xc5, 0xf8,
635 0x14, 0x80, 0x5f, 0xf0, 0x02, 0x08, 0xc5, 0xf8,
636 0x10, 0x80, 0x5f, 0xf0, 0x01, 0x09, 0x00, 0xf0,
637 0x5a, 0xf8, 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1,
638 0x00, 0x0f, 0x00, 0xf0, 0x8b, 0x80, 0x47, 0x68,
639 0x47, 0x45, 0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8,
640 0x01, 0x9b, 0x00, 0xf0, 0x30, 0xf8, 0x8f, 0x42,
641 0x28, 0xbf, 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60,
642 0x01, 0x3b, 0x00, 0x2b, 0x00, 0xf0, 0x05, 0x80,
643 0x02, 0xf1, 0x01, 0x02, 0x92, 0x45, 0x7f, 0xf4,
644 0xe4, 0xaf, 0x00, 0xf0, 0x50, 0xf8, 0xa2, 0x44,
645 0x00, 0xf0, 0x2d, 0xf8, 0x5f, 0xf0, 0x01, 0x08,
646 0xc5, 0xf8, 0x1c, 0x80, 0x5f, 0xf0, 0x00, 0x08,
647 0xc5, 0xf8, 0x20, 0x80, 0x5f, 0xf0, 0x05, 0x08,
648 0xc5, 0xf8, 0x10, 0x80, 0x5f, 0xf0, 0x00, 0x09,
649 0x00, 0xf0, 0x29, 0xf8, 0x00, 0xf0, 0x13, 0xf8,
650 0x09, 0xf0, 0x01, 0x09, 0xb9, 0xf1, 0x00, 0x0f,
651 0xf8, 0xd1, 0x00, 0xf0, 0x34, 0xf8, 0x00, 0x2b,
652 0xa4, 0xd1, 0x00, 0xf0, 0x53, 0xb8, 0xd5, 0xf8,
653 0x00, 0x80, 0x5f, 0xea, 0x08, 0x68, 0xfa, 0xd4,
654 0xc5, 0xf8, 0x08, 0x90, 0x70, 0x47, 0xd5, 0xf8,
655 0x00, 0x80, 0x5f, 0xea, 0xc8, 0x68, 0xfa, 0xd4,
656 0xd5, 0xf8, 0x0c, 0x90, 0x70, 0x47, 0xd5, 0xf8,
657 0x04, 0x80, 0x48, 0xf4, 0x00, 0x78, 0xc5, 0xf8,
658 0x04, 0x80, 0xd5, 0xf8, 0x04, 0x80, 0x5f, 0xea,
659 0x88, 0x58, 0xfa, 0xd4, 0x70, 0x47, 0xd5, 0xf8,
660 0x00, 0x80, 0x48, 0xf0, 0x01, 0x08, 0xc5, 0xf8,
661 0x00, 0x80, 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea,
662 0x88, 0x78, 0xfa, 0xd5, 0xd5, 0xf8, 0x04, 0x80,
663 0x69, 0xf3, 0x4d, 0x38, 0x48, 0xf4, 0x00, 0x48,
664 0xc5, 0xf8, 0x04, 0x80, 0x70, 0x47, 0xd5, 0xf8,
665 0x00, 0x80, 0x5f, 0xea, 0x88, 0x78, 0xfa, 0xd5,
666 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea, 0x48, 0x68,
667 0xfa, 0xd5, 0xd5, 0xf8, 0x04, 0x80, 0x48, 0xf4,
668 0x80, 0x48, 0xc5, 0xf8, 0x04, 0x80, 0xd5, 0xf8,
669 0x04, 0x80, 0x5f, 0xea, 0x08, 0x48, 0xfa, 0xd4,
670 0xd5, 0xf8, 0x00, 0x80, 0x28, 0xf0, 0x01, 0x08,
671 0xc5, 0xf8, 0x00, 0x80, 0xd5, 0xf8, 0x00, 0x80,
672 0x5f, 0xea, 0x88, 0x78, 0xfa, 0xd5, 0x70, 0x47,
673 0x00, 0x20, 0x50, 0x60, 0x30, 0x46, 0x00, 0xbe
676 if (target_alloc_working_area(target
, sizeof(mrvlqspi_flash_write_code
),
677 &write_algorithm
) != ERROR_OK
) {
678 LOG_ERROR("Insufficient working area. You must configure"\
679 " a working area > %zdB in order to write to SPIFI flash.",
680 sizeof(mrvlqspi_flash_write_code
));
681 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
684 retval
= target_write_buffer(target
, write_algorithm
->address
,
685 sizeof(mrvlqspi_flash_write_code
),
686 mrvlqspi_flash_write_code
);
687 if (retval
!= ERROR_OK
) {
688 target_free_working_area(target
, write_algorithm
);
692 /* FIFO allocation */
693 fifo_size
= target_get_working_area_avail(target
);
695 if (fifo_size
== 0) {
696 /* if we already allocated the writing code but failed to get fifo
697 * space, free the algorithm */
698 target_free_working_area(target
, write_algorithm
);
700 LOG_ERROR("Insufficient working area. Please allocate at least"\
701 " %zdB of working area to enable flash writes.",
702 sizeof(mrvlqspi_flash_write_code
) + 1
705 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
706 } else if (fifo_size
< page_size
)
707 LOG_WARNING("Working area size is limited; flash writes may be"\
708 " slow. Increase working area size to at least %zdB"\
709 " to reduce write times.",
710 (size_t)(sizeof(mrvlqspi_flash_write_code
) + page_size
)
713 if (target_alloc_working_area(target
, fifo_size
, &fifo
) != ERROR_OK
) {
714 target_free_working_area(target
, write_algorithm
);
715 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
718 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
719 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
721 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
); /* buffer start, status (out) */
722 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
); /* buffer end */
723 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
); /* target address */
724 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
); /* count (halfword-16bit) */
725 init_reg_param(®_params
[4], "r4", 32, PARAM_OUT
); /* page size */
726 init_reg_param(®_params
[5], "r5", 32, PARAM_OUT
); /* qspi base address */
728 buf_set_u32(reg_params
[0].value
, 0, 32, fifo
->address
);
729 buf_set_u32(reg_params
[1].value
, 0, 32, fifo
->address
+ fifo
->size
);
730 buf_set_u32(reg_params
[2].value
, 0, 32, offset
);
731 buf_set_u32(reg_params
[3].value
, 0, 32, count
);
732 buf_set_u32(reg_params
[4].value
, 0, 32, page_size
);
733 buf_set_u32(reg_params
[5].value
, 0, 32, (uint32_t) mrvlqspi_info
->reg_base
);
735 retval
= target_run_flash_async_algorithm(target
, buffer
, count
, 1,
738 fifo
->address
, fifo
->size
,
739 write_algorithm
->address
, 0,
743 if (retval
!= ERROR_OK
)
744 LOG_ERROR("Error executing flash write algorithm");
746 target_free_working_area(target
, fifo
);
747 target_free_working_area(target
, write_algorithm
);
749 destroy_reg_param(®_params
[0]);
750 destroy_reg_param(®_params
[1]);
751 destroy_reg_param(®_params
[2]);
752 destroy_reg_param(®_params
[3]);
753 destroy_reg_param(®_params
[4]);
754 destroy_reg_param(®_params
[5]);
759 int mrvlqspi_flash_read(struct flash_bank
*bank
, uint8_t *buffer
,
760 uint32_t offset
, uint32_t count
)
762 struct target
*target
= bank
->target
;
763 struct mrvlqspi_flash_bank
*mrvlqspi_info
= bank
->driver_priv
;
767 if (target
->state
!= TARGET_HALTED
) {
768 LOG_ERROR("Target not halted");
769 return ERROR_TARGET_NOT_HALTED
;
772 if (!(mrvlqspi_info
->probed
)) {
773 LOG_ERROR("Flash bank not probed");
774 return ERROR_FLASH_BANK_NOT_PROBED
;
777 /* Flush read/write fifo's */
778 retval
= mrvlqspi_fifo_flush(bank
, FIFO_FLUSH_TIMEOUT
);
779 if (retval
!= ERROR_OK
)
782 /* Set instruction/addr count value */
783 retval
= mrvlqspi_set_hdr_cnt(bank
, (0x1 | (0x3 << 4)));
784 if (retval
!= ERROR_OK
)
787 /* Set count for number of bytes to read */
788 retval
= mrvlqspi_set_din_cnt(bank
, count
);
789 if (retval
!= ERROR_OK
)
792 /* Set read address */
793 retval
= mrvlqspi_set_addr(bank
, offset
);
794 if (retval
!= ERROR_OK
)
797 /* Set instruction */
798 retval
= mrvlqspi_set_instr(bank
, SPIFLASH_READ
);
799 if (retval
!= ERROR_OK
)
802 /* Set data and addr pin length */
803 retval
= mrvlqspi_set_conf(bank
, 0x0);
804 if (retval
!= ERROR_OK
)
807 retval
= mrvlqspi_start_transfer(bank
, QSPI_R_EN
);
808 if (retval
!= ERROR_OK
)
811 for (i
= 0; i
< count
; i
++) {
812 retval
= mrvlqspi_read_byte(bank
, &buffer
[i
]);
813 if (retval
!= ERROR_OK
)
817 retval
= mrvlqspi_set_ss_state(bank
, QSPI_SS_DISABLE
, QSPI_TIMEOUT
);
818 if (retval
!= ERROR_OK
)
824 static int mrvlqspi_probe(struct flash_bank
*bank
)
826 struct target
*target
= bank
->target
;
827 struct mrvlqspi_flash_bank
*mrvlqspi_info
= bank
->driver_priv
;
830 struct flash_sector
*sectors
;
832 /* If we've already probed, we should be fine to skip this time. */
833 if (mrvlqspi_info
->probed
)
836 if (target
->state
!= TARGET_HALTED
) {
837 LOG_ERROR("Target not halted");
838 return ERROR_TARGET_NOT_HALTED
;
841 mrvlqspi_info
->probed
= 0;
842 mrvlqspi_info
->bank_num
= bank
->bank_number
;
844 /* Read flash JEDEC ID */
845 retval
= mrvlqspi_read_id(bank
, &id
);
846 if (retval
!= ERROR_OK
)
849 mrvlqspi_info
->dev
= NULL
;
850 for (const struct flash_device
*p
= flash_devices
; p
->name
; p
++)
851 if (p
->device_id
== id
) {
852 mrvlqspi_info
->dev
= p
;
856 if (!mrvlqspi_info
->dev
) {
857 LOG_ERROR("Unknown flash device ID 0x%08x", id
);
861 LOG_INFO("Found flash device \'%s\' ID 0x%08x",
862 mrvlqspi_info
->dev
->name
, mrvlqspi_info
->dev
->device_id
);
864 /* Set correct size value */
865 bank
->size
= mrvlqspi_info
->dev
->size_in_bytes
;
867 /* create and fill sectors array */
868 bank
->num_sectors
= mrvlqspi_info
->dev
->size_in_bytes
/
869 mrvlqspi_info
->dev
->sectorsize
;
870 sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
871 if (sectors
== NULL
) {
872 LOG_ERROR("not enough memory");
876 for (int sector
= 0; sector
< bank
->num_sectors
; sector
++) {
877 sectors
[sector
].offset
=
878 sector
* mrvlqspi_info
->dev
->sectorsize
;
879 sectors
[sector
].size
= mrvlqspi_info
->dev
->sectorsize
;
880 sectors
[sector
].is_erased
= -1;
881 sectors
[sector
].is_protected
= 0;
884 bank
->sectors
= sectors
;
885 mrvlqspi_info
->probed
= 1;
890 static int mrvlqspi_auto_probe(struct flash_bank
*bank
)
892 struct mrvlqspi_flash_bank
*mrvlqspi_info
= bank
->driver_priv
;
893 if (mrvlqspi_info
->probed
)
895 return mrvlqspi_probe(bank
);
898 static int mrvlqspi_flash_erase_check(struct flash_bank
*bank
)
900 /* Not implemented yet */
904 static int mrvlqspi_protect_check(struct flash_bank
*bank
)
906 /* Not implemented yet */
910 int mrvlqspi_get_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
912 struct mrvlqspi_flash_bank
*mrvlqspi_info
= bank
->driver_priv
;
914 if (!(mrvlqspi_info
->probed
)) {
915 snprintf(buf
, buf_size
,
916 "\nQSPI flash bank not probed yet\n");
920 snprintf(buf
, buf_size
, "\nQSPI flash information:\n"
921 " Device \'%s\' ID 0x%08x\n",
922 mrvlqspi_info
->dev
->name
, mrvlqspi_info
->dev
->device_id
);
927 FLASH_BANK_COMMAND_HANDLER(mrvlqspi_flash_bank_command
)
929 struct mrvlqspi_flash_bank
*mrvlqspi_info
;
932 return ERROR_COMMAND_SYNTAX_ERROR
;
934 mrvlqspi_info
= malloc(sizeof(struct mrvlqspi_flash_bank
));
935 if (mrvlqspi_info
== NULL
) {
936 LOG_ERROR("not enough memory");
940 /* Get QSPI controller register map base address */
941 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[6], mrvlqspi_info
->reg_base
);
942 bank
->driver_priv
= mrvlqspi_info
;
943 mrvlqspi_info
->probed
= 0;
948 struct flash_driver mrvlqspi_flash
= {
950 .flash_bank_command
= mrvlqspi_flash_bank_command
,
951 .erase
= mrvlqspi_flash_erase
,
953 .write
= mrvlqspi_flash_write
,
954 .read
= mrvlqspi_flash_read
,
955 .probe
= mrvlqspi_probe
,
956 .auto_probe
= mrvlqspi_auto_probe
,
957 .erase_check
= mrvlqspi_flash_erase_check
,
958 .protect_check
= mrvlqspi_protect_check
,
959 .info
= mrvlqspi_get_info
,
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)