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.");
451 LOG_WARNING(
"Bulk flash erase failed. Falling back to sector-by-sector erase.");
462 static const uint8_t lpcspifi_flash_erase_code[] = {
463 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a,
464 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81,
465 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81,
466 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81,
467 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81,
468 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81,
469 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81,
470 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
471 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80,
472 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
473 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80,
474 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a,
475 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18,
476 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a,
477 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08,
478 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a,
479 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08,
480 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08,
481 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80,
482 0x00, 0xf0, 0x52, 0xf8, 0x4f, 0xf0, 0x06, 0x09,
483 0x00, 0xf0, 0x3b, 0xf8, 0x00, 0xf0, 0x48, 0xf8,
484 0x00, 0xf0, 0x4a, 0xf8, 0x4f, 0xf0, 0x05, 0x09,
485 0x00, 0xf0, 0x33, 0xf8, 0x4f, 0xf0, 0x00, 0x09,
486 0x00, 0xf0, 0x2f, 0xf8, 0x00, 0xf0, 0x3c, 0xf8,
487 0x19, 0xf0, 0x02, 0x0f, 0x00, 0xf0, 0x45, 0x80,
488 0x00, 0xf0, 0x3a, 0xf8, 0x4f, 0xea, 0x02, 0x09,
489 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xea, 0x10, 0x49,
490 0x00, 0xf0, 0x1f, 0xf8, 0x4f, 0xea, 0x10, 0x29,
491 0x00, 0xf0, 0x1b, 0xf8, 0x4f, 0xea, 0x00, 0x09,
492 0x00, 0xf0, 0x17, 0xf8, 0x00, 0xf0, 0x24, 0xf8,
493 0x00, 0xf0, 0x26, 0xf8, 0x4f, 0xf0, 0x05, 0x09,
494 0x00, 0xf0, 0x0f, 0xf8, 0x4f, 0xf0, 0x00, 0x09,
495 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0xf0, 0x18, 0xf8,
496 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4, 0xf0, 0xaf,
497 0x01, 0x39, 0xf9, 0xb1, 0x18, 0x44, 0xff, 0xf7,
498 0xbf, 0xbf, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2,
499 0x08, 0x0a, 0xca, 0xf8, 0x08, 0x90, 0xda, 0xf8,
500 0x0c, 0x90, 0x19, 0xf0, 0x10, 0x0f, 0x7f, 0xf4,
501 0xfa, 0xaf, 0xda, 0xf8, 0x08, 0x90, 0x70, 0x47,
502 0x4f, 0xf0, 0xff, 0x08, 0x00, 0xf0, 0x02, 0xb8,
503 0x4f, 0xf0, 0x00, 0x08, 0x4f, 0xf4, 0x80, 0x4a,
504 0xc4, 0xf2, 0x0f, 0x0a, 0xca, 0xf8, 0xab, 0x80,
505 0x70, 0x47, 0x00, 0x20, 0x00, 0xbe, 0xff, 0xff
516 LOG_ERROR(
"Insufficient working area. You must configure a working"
517 " area of at least %zdB in order to erase SPIFI flash.",
518 sizeof(lpcspifi_flash_erase_code));
524 sizeof(lpcspifi_flash_erase_code), lpcspifi_flash_erase_code);
536 buf_set_u32(reg_params[1].value, 0, 32, last - first + 1);
543 erase_algorithm->
address +
sizeof(lpcspifi_flash_erase_code) - 4,
544 3000*(last - first + 1), &armv7m_info);
547 LOG_ERROR(
"Error executing flash erase algorithm");
560 unsigned int first,
unsigned int last)
562 for (
unsigned int sector = first; sector <= last; sector++)
563 bank->sectors[sector].is_protected = set;
579 LOG_DEBUG(
"offset=0x%08" PRIx32
" count=0x%08" PRIx32,
588 LOG_WARNING(
"Writes past end of flash. Extra data discarded.");
593 for (
unsigned int sector = 0; sector <
bank->num_sectors; sector++) {
597 (
bank->sectors[sector].offset +
bank->sectors[sector].size))
599 &&
bank->sectors[sector].is_protected) {
600 LOG_ERROR(
"Flash sector %u protected", sector);
614 static const uint8_t lpcspifi_flash_write_code[] = {
615 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a,
616 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81,
617 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81,
618 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81,
619 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81,
620 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81,
621 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81,
622 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
623 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80,
624 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
625 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80,
626 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a,
627 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18,
628 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a,
629 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08,
630 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a,
631 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08,
632 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08,
633 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80,
634 0x4f, 0xf0, 0x00, 0x0b, 0xa3, 0x44, 0x93, 0x45,
635 0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6a, 0xf8,
636 0x4f, 0xf0, 0x06, 0x09, 0x00, 0xf0, 0x53, 0xf8,
637 0x00, 0xf0, 0x60, 0xf8, 0x00, 0xf0, 0x62, 0xf8,
638 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x4b, 0xf8,
639 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x47, 0xf8,
640 0x00, 0xf0, 0x54, 0xf8, 0x19, 0xf0, 0x02, 0x0f,
641 0x00, 0xf0, 0x5d, 0x80, 0x00, 0xf0, 0x52, 0xf8,
642 0x4f, 0xf0, 0x02, 0x09, 0x00, 0xf0, 0x3b, 0xf8,
643 0x4f, 0xea, 0x12, 0x49, 0x00, 0xf0, 0x37, 0xf8,
644 0x4f, 0xea, 0x12, 0x29, 0x00, 0xf0, 0x33, 0xf8,
645 0x4f, 0xea, 0x02, 0x09, 0x00, 0xf0, 0x2f, 0xf8,
646 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f,
647 0x00, 0xf0, 0x47, 0x80, 0x47, 0x68, 0x47, 0x45,
648 0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8, 0x01, 0x9b,
649 0x00, 0xf0, 0x21, 0xf8, 0x8f, 0x42, 0x28, 0xbf,
650 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60, 0x01, 0x3b,
651 0xbb, 0xb3, 0x02, 0xf1, 0x01, 0x02, 0x93, 0x45,
652 0x7f, 0xf4, 0xe6, 0xaf, 0x00, 0xf0, 0x22, 0xf8,
653 0xa3, 0x44, 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xf0,
654 0x05, 0x09, 0x00, 0xf0, 0x0c, 0xf8, 0x4f, 0xf0,
655 0x00, 0x09, 0x00, 0xf0, 0x08, 0xf8, 0x00, 0xf0,
656 0x15, 0xf8, 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4,
657 0xf0, 0xaf, 0xff, 0xf7, 0xa7, 0xbf, 0x4f, 0xf4,
658 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0xca, 0xf8,
659 0x08, 0x90, 0xda, 0xf8, 0x0c, 0x90, 0x19, 0xf0,
660 0x10, 0x0f, 0x7f, 0xf4, 0xfa, 0xaf, 0xda, 0xf8,
661 0x08, 0x90, 0x70, 0x47, 0x4f, 0xf0, 0xff, 0x08,
662 0x00, 0xf0, 0x02, 0xb8, 0x4f, 0xf0, 0x00, 0x08,
663 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
664 0xca, 0xf8, 0xab, 0x80, 0x70, 0x47, 0x00, 0x20,
665 0x50, 0x60, 0xff, 0xf7, 0xef, 0xff, 0x30, 0x46,
666 0x00, 0xbe, 0xff, 0xff
671 LOG_ERROR(
"Insufficient working area. You must configure"
672 " a working area > %zdB in order to write to SPIFI flash.",
673 sizeof(lpcspifi_flash_write_code));
678 sizeof(lpcspifi_flash_write_code),
679 lpcspifi_flash_write_code);
688 if (fifo_size == 0) {
693 LOG_ERROR(
"Insufficient working area. Please allocate at least"
694 " %zdB of working area to enable flash writes.",
695 sizeof(lpcspifi_flash_write_code) + 1
700 LOG_WARNING(
"Working area size is limited; flash writes may be"
701 " slow. Increase working area size to at least %zdB"
702 " to reduce write times.",
703 (
size_t)(
sizeof(lpcspifi_flash_write_code) +
page_size)
705 else if (fifo_size > 0x2000)
737 LOG_ERROR(
"Error executing flash write algorithm");
761 uint8_t id_buf[3] = {0, 0, 0};
821 *
id = id_buf[2] << 16 | id_buf[1] << 8 | id_buf[0];
835 if (lpcspifi_info->
probed)
837 lpcspifi_info->
probed =
false;
839 lpcspifi_info->
ssp_base = 0x40083000;
840 lpcspifi_info->
io_base = 0x400F4000;
855 if (p->device_id ==
id) {
856 lpcspifi_info->
dev = p;
860 if (!lpcspifi_info->
dev) {
861 LOG_ERROR(
"Unknown flash device (ID 0x%08" PRIx32
")",
id);
865 LOG_INFO(
"Found flash device \'%s\' (ID 0x%08" PRIx32
")",
870 if (
bank->size <= (1UL << 16))
871 LOG_WARNING(
"device needs 2-byte addresses - not implemented");
872 if (
bank->size > (1UL << 24))
873 LOG_WARNING(
"device needs paging or 4-byte addresses - not implemented");
887 for (
unsigned int sector = 0; sector <
bank->num_sectors; sector++) {
888 sectors[sector].
offset = sector * sectorsize;
889 sectors[sector].
size = sectorsize;
894 bank->sectors = sectors;
896 lpcspifi_info->
probed =
true;
903 if (lpcspifi_info->
probed)
918 if (!(lpcspifi_info->
probed)) {
924 " Device \'%s\' (ID 0x%08" PRIx32
")\n",
932 .flash_bank_command = lpcspifi_flash_bank_command,
void init_reg_param(struct reg_param *param, const 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...
uint64_t buffer
Pointer to data buffer to send over SPI.
uint32_t page_size
Page size.
#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