20 #define SSP_CR0 (0x00)
21 #define SSP_CR1 (0x04)
22 #define SSP_DATA (0x08)
24 #define SSP_CPSR (0x10)
27 #define SSP_BSY (0x00000010)
30 #define SSP_CMD_TIMEOUT (100)
31 #define SSP_PROBE_TIMEOUT (100)
32 #define SSP_MAX_TIMEOUT (3000)
36 #define SPIFI_INIT_STACK_SIZE 512
63 bank->driver_priv = lpcspifi_info;
64 lpcspifi_info->
probed =
false;
140 static const uint8_t spifi_init_code[] = {
141 0x4f, 0xea, 0x00, 0x08, 0xa1, 0xb0, 0x00, 0xaf,
142 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03,
143 0x4f, 0xf0, 0xf3, 0x02, 0xc3, 0xf8, 0x8c, 0x21,
144 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03,
145 0x4f, 0xf4, 0xc0, 0x42, 0xc4, 0xf2, 0x08, 0x02,
146 0x4f, 0xf4, 0xc0, 0x41, 0xc4, 0xf2, 0x08, 0x01,
147 0x4f, 0xf4, 0xc0, 0x40, 0xc4, 0xf2, 0x08, 0x00,
148 0x4f, 0xf0, 0xd3, 0x04, 0xc0, 0xf8, 0x9c, 0x41,
149 0x20, 0x46, 0xc1, 0xf8, 0x98, 0x01, 0x01, 0x46,
150 0xc2, 0xf8, 0x94, 0x11, 0xc3, 0xf8, 0x90, 0x11,
151 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03,
152 0x4f, 0xf0, 0x13, 0x02, 0xc3, 0xf8, 0xa0, 0x21,
153 0x40, 0xf2, 0x18, 0x13, 0xc1, 0xf2, 0x40, 0x03,
154 0x1b, 0x68, 0x1c, 0x68, 0x40, 0xf2, 0xb4, 0x30,
155 0xc1, 0xf2, 0x00, 0x00, 0x4f, 0xf0, 0x03, 0x01,
156 0x4f, 0xf0, 0xc0, 0x02, 0x4f, 0xea, 0x08, 0x03,
157 0xa0, 0x47, 0x00, 0xf0, 0x00, 0xb8, 0x00, 0xbe
164 LOG_DEBUG(
"Allocating working area for SPIFI init algorithm");
169 LOG_ERROR(
"Insufficient working area to initialize SPIFI "
170 "module. You must allocate at least %zdB of working "
171 "area in order to use this driver.",
179 spifi_init_algorithm->
address);
183 sizeof(spifi_init_code),
207 LOG_DEBUG(
"Running SPIFI init algorithm");
210 spifi_init_algorithm->
address +
sizeof(spifi_init_code) - 2,
214 LOG_ERROR(
"Error executing SPIFI init algorithm");
331 LOG_ERROR(
"timeout waiting for flash to finish write/erase operation");
363 LOG_ERROR(
"Cannot enable write to flash. Status=0x%08" PRIx32,
status);
416 LOG_DEBUG(
"erase from sector %u to sector %u", first, last);
423 if ((last < first) || (last >=
bank->num_sectors)) {
428 if (!(lpcspifi_info->
probed)) {
433 for (
unsigned int sector = first; sector <= last; sector++) {
434 if (
bank->sectors[sector].is_protected) {
435 LOG_ERROR(
"Flash sector %u protected", sector);
442 if (first == 0 && last == (
bank->num_sectors - 1)
444 LOG_DEBUG(
"Chip supports the bulk erase command."
445 " Will use bulk erase instead of sector-by-sector erase.");
452 LOG_WARNING(
"Bulk flash erase failed. Falling back to sector-by-sector erase.");
463 static const uint8_t lpcspifi_flash_erase_code[] = {
464 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a,
465 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81,
466 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81,
467 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81,
468 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81,
469 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81,
470 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81,
471 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
472 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80,
473 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
474 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80,
475 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a,
476 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18,
477 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a,
478 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08,
479 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a,
480 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08,
481 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08,
482 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80,
483 0x00, 0xf0, 0x52, 0xf8, 0x4f, 0xf0, 0x06, 0x09,
484 0x00, 0xf0, 0x3b, 0xf8, 0x00, 0xf0, 0x48, 0xf8,
485 0x00, 0xf0, 0x4a, 0xf8, 0x4f, 0xf0, 0x05, 0x09,
486 0x00, 0xf0, 0x33, 0xf8, 0x4f, 0xf0, 0x00, 0x09,
487 0x00, 0xf0, 0x2f, 0xf8, 0x00, 0xf0, 0x3c, 0xf8,
488 0x19, 0xf0, 0x02, 0x0f, 0x00, 0xf0, 0x45, 0x80,
489 0x00, 0xf0, 0x3a, 0xf8, 0x4f, 0xea, 0x02, 0x09,
490 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xea, 0x10, 0x49,
491 0x00, 0xf0, 0x1f, 0xf8, 0x4f, 0xea, 0x10, 0x29,
492 0x00, 0xf0, 0x1b, 0xf8, 0x4f, 0xea, 0x00, 0x09,
493 0x00, 0xf0, 0x17, 0xf8, 0x00, 0xf0, 0x24, 0xf8,
494 0x00, 0xf0, 0x26, 0xf8, 0x4f, 0xf0, 0x05, 0x09,
495 0x00, 0xf0, 0x0f, 0xf8, 0x4f, 0xf0, 0x00, 0x09,
496 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0xf0, 0x18, 0xf8,
497 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4, 0xf0, 0xaf,
498 0x01, 0x39, 0xf9, 0xb1, 0x18, 0x44, 0xff, 0xf7,
499 0xbf, 0xbf, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2,
500 0x08, 0x0a, 0xca, 0xf8, 0x08, 0x90, 0xda, 0xf8,
501 0x0c, 0x90, 0x19, 0xf0, 0x10, 0x0f, 0x7f, 0xf4,
502 0xfa, 0xaf, 0xda, 0xf8, 0x08, 0x90, 0x70, 0x47,
503 0x4f, 0xf0, 0xff, 0x08, 0x00, 0xf0, 0x02, 0xb8,
504 0x4f, 0xf0, 0x00, 0x08, 0x4f, 0xf4, 0x80, 0x4a,
505 0xc4, 0xf2, 0x0f, 0x0a, 0xca, 0xf8, 0xab, 0x80,
506 0x70, 0x47, 0x00, 0x20, 0x00, 0xbe, 0xff, 0xff
517 LOG_ERROR(
"Insufficient working area. You must configure a working"
518 " area of at least %zdB in order to erase SPIFI flash.",
519 sizeof(lpcspifi_flash_erase_code));
525 sizeof(lpcspifi_flash_erase_code), lpcspifi_flash_erase_code);
537 buf_set_u32(reg_params[1].value, 0, 32, last - first + 1);
544 erase_algorithm->
address +
sizeof(lpcspifi_flash_erase_code) - 4,
545 3000*(last - first + 1), &armv7m_info);
548 LOG_ERROR(
"Error executing flash erase algorithm");
563 unsigned int first,
unsigned int last)
565 for (
unsigned int sector = first; sector <= last; sector++)
566 bank->sectors[sector].is_protected = set;
575 uint32_t page_size, fifo_size;
582 LOG_DEBUG(
"offset=0x%08" PRIx32
" count=0x%08" PRIx32,
591 LOG_WARNING(
"Writes past end of flash. Extra data discarded.");
596 for (
unsigned int sector = 0; sector <
bank->num_sectors; sector++) {
600 (
bank->sectors[sector].offset +
bank->sectors[sector].size))
602 &&
bank->sectors[sector].is_protected) {
603 LOG_ERROR(
"Flash sector %u protected", sector);
617 static const uint8_t lpcspifi_flash_write_code[] = {
618 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a,
619 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81,
620 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81,
621 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81,
622 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81,
623 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81,
624 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81,
625 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
626 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80,
627 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
628 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80,
629 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a,
630 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18,
631 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a,
632 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08,
633 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a,
634 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08,
635 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08,
636 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80,
637 0x4f, 0xf0, 0x00, 0x0b, 0xa3, 0x44, 0x93, 0x45,
638 0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6a, 0xf8,
639 0x4f, 0xf0, 0x06, 0x09, 0x00, 0xf0, 0x53, 0xf8,
640 0x00, 0xf0, 0x60, 0xf8, 0x00, 0xf0, 0x62, 0xf8,
641 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x4b, 0xf8,
642 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x47, 0xf8,
643 0x00, 0xf0, 0x54, 0xf8, 0x19, 0xf0, 0x02, 0x0f,
644 0x00, 0xf0, 0x5d, 0x80, 0x00, 0xf0, 0x52, 0xf8,
645 0x4f, 0xf0, 0x02, 0x09, 0x00, 0xf0, 0x3b, 0xf8,
646 0x4f, 0xea, 0x12, 0x49, 0x00, 0xf0, 0x37, 0xf8,
647 0x4f, 0xea, 0x12, 0x29, 0x00, 0xf0, 0x33, 0xf8,
648 0x4f, 0xea, 0x02, 0x09, 0x00, 0xf0, 0x2f, 0xf8,
649 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f,
650 0x00, 0xf0, 0x47, 0x80, 0x47, 0x68, 0x47, 0x45,
651 0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8, 0x01, 0x9b,
652 0x00, 0xf0, 0x21, 0xf8, 0x8f, 0x42, 0x28, 0xbf,
653 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60, 0x01, 0x3b,
654 0xbb, 0xb3, 0x02, 0xf1, 0x01, 0x02, 0x93, 0x45,
655 0x7f, 0xf4, 0xe6, 0xaf, 0x00, 0xf0, 0x22, 0xf8,
656 0xa3, 0x44, 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xf0,
657 0x05, 0x09, 0x00, 0xf0, 0x0c, 0xf8, 0x4f, 0xf0,
658 0x00, 0x09, 0x00, 0xf0, 0x08, 0xf8, 0x00, 0xf0,
659 0x15, 0xf8, 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4,
660 0xf0, 0xaf, 0xff, 0xf7, 0xa7, 0xbf, 0x4f, 0xf4,
661 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0xca, 0xf8,
662 0x08, 0x90, 0xda, 0xf8, 0x0c, 0x90, 0x19, 0xf0,
663 0x10, 0x0f, 0x7f, 0xf4, 0xfa, 0xaf, 0xda, 0xf8,
664 0x08, 0x90, 0x70, 0x47, 0x4f, 0xf0, 0xff, 0x08,
665 0x00, 0xf0, 0x02, 0xb8, 0x4f, 0xf0, 0x00, 0x08,
666 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
667 0xca, 0xf8, 0xab, 0x80, 0x70, 0x47, 0x00, 0x20,
668 0x50, 0x60, 0xff, 0xf7, 0xef, 0xff, 0x30, 0x46,
669 0x00, 0xbe, 0xff, 0xff
674 LOG_ERROR(
"Insufficient working area. You must configure"
675 " a working area > %zdB in order to write to SPIFI flash.",
676 sizeof(lpcspifi_flash_write_code));
681 sizeof(lpcspifi_flash_write_code),
682 lpcspifi_flash_write_code);
691 if (fifo_size == 0) {
696 LOG_ERROR(
"Insufficient working area. Please allocate at least"
697 " %zdB of working area to enable flash writes.",
698 sizeof(lpcspifi_flash_write_code) + 1
702 }
else if (fifo_size < page_size)
703 LOG_WARNING(
"Working area size is limited; flash writes may be"
704 " slow. Increase working area size to at least %zdB"
705 " to reduce write times.",
706 (
size_t)(
sizeof(lpcspifi_flash_write_code) + page_size)
708 else if (fifo_size > 0x2000)
729 buf_set_u32(reg_params[4].value, 0, 32, page_size);
740 LOG_ERROR(
"Error executing flash write algorithm");
765 uint8_t id_buf[3] = {0, 0, 0};
825 *
id = id_buf[2] << 16 | id_buf[1] << 8 | id_buf[0];
839 if (lpcspifi_info->
probed)
841 lpcspifi_info->
probed =
false;
843 lpcspifi_info->
ssp_base = 0x40083000;
844 lpcspifi_info->
io_base = 0x400F4000;
859 if (p->device_id ==
id) {
860 lpcspifi_info->
dev = p;
864 if (!lpcspifi_info->
dev) {
865 LOG_ERROR(
"Unknown flash device (ID 0x%08" PRIx32
")",
id);
869 LOG_INFO(
"Found flash device \'%s\' (ID 0x%08" PRIx32
")",
874 if (
bank->size <= (1UL << 16))
875 LOG_WARNING(
"device needs 2-byte addresses - not implemented");
876 if (
bank->size > (1UL << 24))
877 LOG_WARNING(
"device needs paging or 4-byte addresses - not implemented");
891 for (
unsigned int sector = 0; sector <
bank->num_sectors; sector++) {
892 sectors[sector].
offset = sector * sectorsize;
893 sectors[sector].
size = sectorsize;
898 bank->sectors = sectors;
900 lpcspifi_info->
probed =
true;
907 if (lpcspifi_info->
probed)
922 if (!(lpcspifi_info->
probed)) {
928 " Device \'%s\' (ID 0x%08" PRIx32
")\n",
936 .flash_bank_command = lpcspifi_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
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 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 ERROR_FLASH_OPER_UNSUPPORTED
#define ERROR_FLASH_SECTOR_INVALID
#define ERROR_FLASH_BANK_NOT_PROBED
#define ERROR_FLASH_OPERATION_FAILED
int default_flash_blank_check(struct flash_bank *bank)
Provides default erased-bank check handling.
int default_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
Provides default read implementation for flash memory.
void default_flash_free_driver_priv(struct flash_bank *bank)
Deallocates bank->driver_priv.
The JTAG interface can be implemented with a software or hardware fifo.
void alive_sleep(uint64_t ms)
#define LOG_WARNING(expr ...)
#define LOG_ERROR(expr ...)
#define LOG_INFO(expr ...)
#define LOG_DEBUG(expr ...)
#define SSP_PROBE_TIMEOUT
static int lpcspifi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
static int ssp_setcs(struct target *target, uint32_t io_base, unsigned int value)
static int get_lpcspifi_info(struct flash_bank *bank, struct command_invocation *cmd)
static int lpcspifi_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last)
FLASH_BANK_COMMAND_HANDLER(lpcspifi_flash_bank_command)
static int lpcspifi_auto_probe(struct flash_bank *bank)
static int poll_ssp_busy(struct target *target, uint32_t ssp_base, int timeout)
static int read_status_reg(struct flash_bank *bank, uint32_t *status)
static int lpcspifi_protect_check(struct flash_bank *bank)
static int ssp_read_reg(struct target *target, uint32_t ssp_base, uint32_t offset, uint32_t *value)
static int ioconfig_write_reg(struct target *target, uint32_t ioconfig_base, uint32_t offset, uint32_t value)
static int lpcspifi_write_enable(struct flash_bank *bank)
static int io_write_reg(struct target *target, uint32_t io_base, uint32_t offset, uint32_t value)
#define SPIFI_INIT_STACK_SIZE
static int wait_till_ready(struct flash_bank *bank, int timeout)
const struct flash_driver lpcspifi_flash
static int lpcspifi_set_sw_mode(struct flash_bank *bank)
static int lpcspifi_bulk_erase(struct flash_bank *bank)
static int ssp_write_reg(struct target *target, uint32_t ssp_base, uint32_t offset, uint32_t value)
static int lpcspifi_read_flash_id(struct flash_bank *bank, uint32_t *id)
static int lpcspifi_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
static int lpcspifi_probe(struct flash_bank *bank)
static int lpcspifi_set_hw_mode(struct flash_bank *bank)
const struct flash_device flash_devices[]
#define SPIFLASH_READ_STATUS
#define SPIFLASH_WRITE_ENABLE
#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
uint32_t max_spi_clock_mhz
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
int target_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_param, target_addr_t entry_point, target_addr_t exit_point, unsigned int timeout_ms, void *arch_info)
Downloads a target-specific native code algorithm to the target, and executes it.
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