25 #define QSPI_R_EN (0x0)
26 #define QSPI_W_EN (0x1)
27 #define QSPI_SS_DISABLE (0x0)
28 #define QSPI_SS_ENABLE (0x1)
29 #define WRITE_DISABLE (0x0)
30 #define WRITE_ENABLE (0x1)
32 #define QSPI_TIMEOUT (1000)
33 #define FIFO_FLUSH_TIMEOUT (1000)
34 #define BLOCK_ERASE_TIMEOUT (1000)
35 #define CHIP_ERASE_TIMEOUT (10000)
37 #define SS_EN (1 << 0)
38 #define XFER_RDY (1 << 1)
39 #define RFIFO_EMPTY (1 << 4)
40 #define WFIFO_EMPTY (1 << 6)
41 #define WFIFO_FULL (1 << 7)
42 #define FIFO_FLUSH (1 << 9)
43 #define RW_EN (1 << 13)
44 #define XFER_STOP (1 << 14)
45 #define XFER_START (1 << 15)
46 #define CONF_MASK (0x7)
47 #define CONF_OFFSET (10)
49 #define INS_WRITE_ENABLE 0x06
50 #define INS_WRITE_DISABLE 0x04
51 #define INS_READ_STATUS 0x05
52 #define INS_PAGE_PROGRAM 0x02
150 LOG_DEBUG(
"status: 0x%08" PRIx32, regval);
154 LOG_ERROR(
"timed out waiting for flash");
205 LOG_DEBUG(
"status: 0x%08" PRIx32, regval);
210 LOG_ERROR(
"timed out waiting for flash");
234 LOG_DEBUG(
"status: 0x%08" PRIx32, regval);
238 LOG_ERROR(
"timed out waiting for flash");
279 LOG_ERROR(
"timed out waiting for flash");
357 LOG_ERROR(
"timed out waiting for flash");
404 uint8_t id_buf[3] = {0, 0, 0};
438 for (i = 0; i < 3; i++) {
444 LOG_DEBUG(
"ID is 0x%02" PRIx8
" 0x%02" PRIx8
" 0x%02" PRIx8,
445 id_buf[0], id_buf[1], id_buf[2]);
450 *
id = id_buf[2] << 16 | id_buf[1] << 8 | id_buf[0];
526 LOG_DEBUG(
"erase from sector %u to sector %u", first, last);
533 if ((last < first) || (last >=
bank->num_sectors)) {
538 if (!(mrvlqspi_info->
probed)) {
543 for (
unsigned int sector = first; sector <= last; sector++) {
544 if (
bank->sectors[sector].is_protected) {
545 LOG_ERROR(
"Flash sector %u protected", sector);
552 if (first == 0 && last == (
bank->num_sectors - 1)
555 LOG_DEBUG(
"Chip supports the bulk erase command."
556 " Will use bulk erase instead of sector-by-sector erase.");
562 " Falling back to sector-by-sector erase.");
568 for (
unsigned int sector = first; sector <= last; sector++) {
584 uint32_t page_size, fifo_size;
590 LOG_DEBUG(
"offset=0x%08" PRIx32
" count=0x%08" PRIx32,
599 LOG_WARNING(
"Writes past end of flash. Extra data discarded.");
604 for (
unsigned int sector = 0; sector <
bank->num_sectors; sector++) {
608 (
bank->sectors[sector].offset +
bank->sectors[sector].size))
610 &&
bank->sectors[sector].is_protected) {
611 LOG_ERROR(
"Flash sector %u protected", sector);
621 static const uint8_t mrvlqspi_flash_write_code[] = {
622 0x4f, 0xf0, 0x00, 0x0a, 0xa2, 0x44, 0x92, 0x45,
623 0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6b, 0xf8,
624 0x5f, 0xf0, 0x01, 0x08, 0xc5, 0xf8, 0x1c, 0x80,
625 0x5f, 0xf0, 0x06, 0x08, 0xc5, 0xf8, 0x10, 0x80,
626 0x5f, 0xf0, 0x01, 0x09, 0x00, 0xf0, 0x6b, 0xf8,
627 0x00, 0xf0, 0x7d, 0xf8, 0x5f, 0xf0, 0x31, 0x08,
628 0xc5, 0xf8, 0x1c, 0x80, 0x90, 0x46, 0xc5, 0xf8,
629 0x14, 0x80, 0x5f, 0xf0, 0x02, 0x08, 0xc5, 0xf8,
630 0x10, 0x80, 0x5f, 0xf0, 0x01, 0x09, 0x00, 0xf0,
631 0x5a, 0xf8, 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1,
632 0x00, 0x0f, 0x00, 0xf0, 0x8b, 0x80, 0x47, 0x68,
633 0x47, 0x45, 0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8,
634 0x01, 0x9b, 0x00, 0xf0, 0x30, 0xf8, 0x8f, 0x42,
635 0x28, 0xbf, 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60,
636 0x01, 0x3b, 0x00, 0x2b, 0x00, 0xf0, 0x05, 0x80,
637 0x02, 0xf1, 0x01, 0x02, 0x92, 0x45, 0x7f, 0xf4,
638 0xe4, 0xaf, 0x00, 0xf0, 0x50, 0xf8, 0xa2, 0x44,
639 0x00, 0xf0, 0x2d, 0xf8, 0x5f, 0xf0, 0x01, 0x08,
640 0xc5, 0xf8, 0x1c, 0x80, 0x5f, 0xf0, 0x00, 0x08,
641 0xc5, 0xf8, 0x20, 0x80, 0x5f, 0xf0, 0x05, 0x08,
642 0xc5, 0xf8, 0x10, 0x80, 0x5f, 0xf0, 0x00, 0x09,
643 0x00, 0xf0, 0x29, 0xf8, 0x00, 0xf0, 0x13, 0xf8,
644 0x09, 0xf0, 0x01, 0x09, 0xb9, 0xf1, 0x00, 0x0f,
645 0xf8, 0xd1, 0x00, 0xf0, 0x34, 0xf8, 0x00, 0x2b,
646 0xa4, 0xd1, 0x00, 0xf0, 0x53, 0xb8, 0xd5, 0xf8,
647 0x00, 0x80, 0x5f, 0xea, 0x08, 0x68, 0xfa, 0xd4,
648 0xc5, 0xf8, 0x08, 0x90, 0x70, 0x47, 0xd5, 0xf8,
649 0x00, 0x80, 0x5f, 0xea, 0xc8, 0x68, 0xfa, 0xd4,
650 0xd5, 0xf8, 0x0c, 0x90, 0x70, 0x47, 0xd5, 0xf8,
651 0x04, 0x80, 0x48, 0xf4, 0x00, 0x78, 0xc5, 0xf8,
652 0x04, 0x80, 0xd5, 0xf8, 0x04, 0x80, 0x5f, 0xea,
653 0x88, 0x58, 0xfa, 0xd4, 0x70, 0x47, 0xd5, 0xf8,
654 0x00, 0x80, 0x48, 0xf0, 0x01, 0x08, 0xc5, 0xf8,
655 0x00, 0x80, 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea,
656 0x88, 0x78, 0xfa, 0xd5, 0xd5, 0xf8, 0x04, 0x80,
657 0x69, 0xf3, 0x4d, 0x38, 0x48, 0xf4, 0x00, 0x48,
658 0xc5, 0xf8, 0x04, 0x80, 0x70, 0x47, 0xd5, 0xf8,
659 0x00, 0x80, 0x5f, 0xea, 0x88, 0x78, 0xfa, 0xd5,
660 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea, 0x48, 0x68,
661 0xfa, 0xd5, 0xd5, 0xf8, 0x04, 0x80, 0x48, 0xf4,
662 0x80, 0x48, 0xc5, 0xf8, 0x04, 0x80, 0xd5, 0xf8,
663 0x04, 0x80, 0x5f, 0xea, 0x08, 0x48, 0xfa, 0xd4,
664 0xd5, 0xf8, 0x00, 0x80, 0x28, 0xf0, 0x01, 0x08,
665 0xc5, 0xf8, 0x00, 0x80, 0xd5, 0xf8, 0x00, 0x80,
666 0x5f, 0xea, 0x88, 0x78, 0xfa, 0xd5, 0x70, 0x47,
667 0x00, 0x20, 0x50, 0x60, 0x30, 0x46, 0x00, 0xbe
672 LOG_ERROR(
"Insufficient working area. You must configure"
673 " a working area > %zdB in order to write to SPIFI flash.",
674 sizeof(mrvlqspi_flash_write_code));
679 sizeof(mrvlqspi_flash_write_code),
680 mrvlqspi_flash_write_code);
689 if (fifo_size == 0) {
694 LOG_ERROR(
"Insufficient working area. Please allocate at least"
695 " %zdB of working area to enable flash writes.",
696 sizeof(mrvlqspi_flash_write_code) + 1
700 }
else if (fifo_size < page_size)
701 LOG_WARNING(
"Working area size is limited; flash writes may be"
702 " slow. Increase working area size to at least %zdB"
703 " to reduce write times.",
704 (
size_t)(
sizeof(mrvlqspi_flash_write_code) + page_size)
726 buf_set_u32(reg_params[4].value, 0, 32, page_size);
738 LOG_ERROR(
"Error executing flash write algorithm");
766 if (!(mrvlqspi_info->
probed)) {
805 for (i = 0; i <
count; i++) {
828 if (mrvlqspi_info->
probed)
836 mrvlqspi_info->
probed =
false;
846 if (p->device_id ==
id) {
847 mrvlqspi_info->
dev = p;
851 if (!mrvlqspi_info->
dev) {
852 LOG_ERROR(
"Unknown flash device ID 0x%08" PRIx32,
id);
856 LOG_INFO(
"Found flash device \'%s\' ID 0x%08" PRIx32,
862 if (
bank->size <= (1UL << 16))
863 LOG_WARNING(
"device needs 2-byte addresses - not implemented");
864 if (
bank->size > (1UL << 24))
865 LOG_WARNING(
"device needs paging or 4-byte addresses - not implemented");
879 for (
unsigned int sector = 0; sector <
bank->num_sectors; sector++) {
880 sectors[sector].
offset = sector * sectorsize;
881 sectors[sector].
size = sectorsize;
886 bank->sectors = sectors;
887 mrvlqspi_info->
probed =
true;
895 if (mrvlqspi_info->
probed)
910 if (!(mrvlqspi_info->
probed)) {
916 " Device \'%s\' ID 0x%08" PRIx32
"\n",
930 if (!mrvlqspi_info) {
937 bank->driver_priv = mrvlqspi_info;
938 mrvlqspi_info->
probed =
false;
945 .flash_bank_command = mrvlqspi_flash_bank_command,
void init_reg_param(struct reg_param *param, char *reg_name, uint32_t size, enum param_direction direction)
void destroy_reg_param(struct reg_param *param)
#define ARMV7M_COMMON_MAGIC
Support functions to access arbitrary bits in a byte array.
static void buf_set_u32(uint8_t *_buffer, unsigned int first, unsigned int num, uint32_t value)
Sets num bits in _buffer, starting at the first bit, using the bits in value.
void command_print_sameline(struct command_invocation *cmd, const char *format,...)
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
#define ERROR_COMMAND_SYNTAX_ERROR
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
#define COMMAND_PARSE_NUMBER(type, in, out)
parses the string in into out as a type, or prints a command error and passes the error code to the c...
#define ERROR_FLASH_OPER_UNSUPPORTED
#define ERROR_FLASH_SECTOR_INVALID
#define ERROR_FLASH_BANK_NOT_PROBED
void default_flash_free_driver_priv(struct flash_bank *bank)
Deallocates bank->driver_priv.
void alive_sleep(uint64_t ms)
#define LOG_WARNING(expr ...)
#define LOG_ERROR(expr ...)
#define LOG_INFO(expr ...)
#define LOG_DEBUG(expr ...)
#define INS_WRITE_DISABLE
static int mrvlqspi_fifo_flush(struct flash_bank *bank, int timeout)
static int mrvlqspi_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
static int mrvlqspi_flash_erase_check(struct flash_bank *bank)
static uint32_t mrvlqspi_get_reg(struct flash_bank *bank, uint32_t reg)
static int mrvlqspi_set_hdr_cnt(struct flash_bank *bank, uint32_t hdr_cnt)
FLASH_BANK_COMMAND_HANDLER(mrvlqspi_flash_bank_command)
static int mrvlqspi_set_din_cnt(struct flash_bank *bank, uint32_t count)
static int mrvlqspi_start_transfer(struct flash_bank *bank, bool rw_mode)
static int mrvlqspi_flash_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
static int mrvlqspi_flash_busy_status(struct flash_bank *bank, int timeout)
static int mrvlqspi_set_instr(struct flash_bank *bank, uint32_t instr)
static int mrvlqspi_get_info(struct flash_bank *bank, struct command_invocation *cmd)
static int mrvlqspi_set_addr(struct flash_bank *bank, uint32_t addr)
#define CHIP_ERASE_TIMEOUT
const struct flash_driver mrvlqspi_flash
static int mrvlqspi_block_erase(struct flash_bank *bank, uint32_t offset)
#define BLOCK_ERASE_TIMEOUT
#define FIFO_FLUSH_TIMEOUT
static int mrvlqspi_set_write_status(struct flash_bank *bank, bool mode)
static int mrvlqspi_read_byte(struct flash_bank *bank, uint8_t *data)
static int mrvlqspi_probe(struct flash_bank *bank)
static int mrvlqspi_stop_transfer(struct flash_bank *bank)
static int mrvlqspi_auto_probe(struct flash_bank *bank)
static int mrvlqspi_read_id(struct flash_bank *bank, uint32_t *id)
static int mrvlqspi_set_ss_state(struct flash_bank *bank, bool state, int timeout)
static int mrvlqspi_bulk_erase(struct flash_bank *bank)
static int mrvlqspi_set_conf(struct flash_bank *bank, uint32_t conf_val)
target_addr_t addr
Start address to search for the control block.
const struct flash_device flash_devices[]
#define SPIFLASH_DEF_PAGESIZE
unsigned int common_magic
When run_command is called, a new instance will be created on the stack, filled with the proper value...
Provides details of a flash bank, available either on-chip or through a major interface.
Provides the implementation-independent structure that defines all of the callbacks required by OpenO...
const char * name
Gives a human-readable name of this flash driver, This field is used to select and initialize the dri...
Describes the geometry and status of a single flash sector within a flash bank.
int is_erased
Indication of erasure status: 0 = not erased, 1 = erased, other = unknown.
uint32_t offset
Bus offset from start of the flash chip (in bytes).
int is_protected
Indication of protection status: 0 = unprotected/unlocked, 1 = protected/locked, other = unknown.
uint32_t size
Number of bytes in this flash sector.
const struct flash_device * dev
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
uint32_t target_get_working_area_avail(struct target *target)
int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area)
int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
int target_free_working_area(struct target *target, struct working_area *area)
Free a working area.
int target_run_flash_async_algorithm(struct target *target, const uint8_t *buffer, uint32_t count, int block_size, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t buffer_start, uint32_t buffer_size, uint32_t entry_point, uint32_t exit_point, void *arch_info)
Streams data to a circular buffer on target intended for consumption by code running asynchronously o...
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
#define ERROR_TARGET_NOT_HALTED
#define ERROR_TARGET_RESOURCE_NOT_AVAILABLE