This is an automated email from Gerrit.

Andreas Bolsch (hyphen0br...@gmail.com) just uploaded a new patch set to 
Gerrit, which you can find at http://openocd.zylin.com/3918

-- gerrit

commit bc9b8777c3efdd0359076f9849f0bcca42d76693
Author: Andreas Bolsch <hyphen0br...@gmail.com>
Date:   Wed Dec 21 10:35:58 2016 +0100

    Flash driver for QUADSPI interface in various STM32 variants.
    
    Changes relative to #3162:
    - programming in stmqspi now using "target_run_flash_async_algorithm",
      on STM32F746G-discovery approx. 30% reduction of programming time
    - write speed up to 100 kByte/s on STM32L476G-discovery
    - tested with STM32F746G-discovery (128Mbit flash, 3-byte addresses),
      STM32F769I-discovery (512Mbit flash, 4-byte addresses), and
      STM32L476G-discovery (128Mbit flash, 3-byte addresses)
    - suitable cfg for STM32F746G-discovery, STM32F769I-discovery,
      and STM32L476G-discovery included
    - additional sanity check regarding flash size vs. FSIZE field
    - protection now disengaged by default
    - some LOG messages changed from USER to DEBUG
    
    What's left from comments on #3162:
    - return from within macro
    
    Untested:
    - dual flash mode (sorry, no appropriate hardware available)
    
    Requirements:
    GPIOs must be initialized appropriately, and SPI flash chip be configured
    to simple spi (aka 1-line) mode and to 4-byte addresses depending on 
capacity.
    This is board/chip specific, cf. included cfg files.
    
    Note that 'flash write_image' with automatic erase is NOT feasible if huge
    portion of spi flash is to be rewritten. Sector erase is incredible slow
    for large capacity flash (one second per sector), so always prefer
    'stmqspi mass_erase' when possible.
    
    Disappointing: Read/verify is much slower than write :-(
    Read and verify is not done by stmqspi, however. On STM32L476G-disco
    'adapter_khz 4000' allows 100kByte/s write speed successfully, whereas
    even at 'adapter_khz 2000' st-link crashes instantly on read/verify.
    Only after power-up reset a reconnect is possible ...
    
    Change-Id: Id584afec683d32c26cbb418e92f70623ddaa2f31
    Signed-off-by: Andreas Bolsch <hyphen0br...@gmail.com>

diff --git a/contrib/loaders/flash/stmqspi.S b/contrib/loaders/flash/stmqspi.S
index dd47382..3d91fe5 100644
--- a/contrib/loaders/flash/stmqspi.S
+++ b/contrib/loaders/flash/stmqspi.S
@@ -1,6 +1,6 @@
 
 /***************************************************************************
- *   Copyright (C) 2015 by Andreas Bolsch                                  *
+ *   Copyright (C) 2016 by Andreas Bolsch                                  *
  *   andreas.bol...@mni.thm.de                                             *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -34,14 +34,17 @@
  */
 
 /* Params:
- * r0 - total count (bytes)
+ * r0 - total count (bytes), status (out)
  * r1 - flash page size
- * r2 - adress offset into flash
+ * r2 - address offset into flash
  * r3 - QSPI io_base
+ * r8 - fifo start
+ * r9 - fifo end + 1
+
  * Clobbered:
- * r4 - QSPI DR address
- * r5 - ptr into buffer
- * r6 - single / dual
+ * r4 - rp
+ * r5 - offset of QSPI_DR
+ * r6 - single 0x0 / dual 0x1
  * r7 - tmp
  */
 
@@ -49,120 +52,130 @@
 
        .macro  wait_busy
 0:
-       ldr             r7, [r3, #QSPI_SR]              /* load status */
-       lsrs    r7, r7, #(QSPI_BUSY+1)  /* shift BUSY into C */
-       bcs             0b                                              /* loop 
till BUSY cleared */
-       movs    r7, #(1<<QSPI_TCF)              /* TCF bitmask */
-       str             r7, [r3, #QSPI_FCR]             /* clear TCF flag */
-       .endm
-
-       .macro  wait_fifo
-1:
-       ldr             r7,     [r3, #QSPI_SR]          /* load status */
-       lsrs    r7, #(QSPI_FTF+1)               /* wait for FTF to be set */
-       bcc             1b                                              /* if 
not, then test again */
+       ldr             r7, [r3, #QSPI_SR]                      /* load status 
*/
+       lsrs    r7, r7, #(QSPI_BUSY+1)          /* shift BUSY into C */
+       bcs             0b                                                      
/* loop till BUSY cleared */
+       movs    r7, #(1<<QSPI_TCF)                      /* TCF bitmask */
+       str             r7, [r3, #QSPI_FCR]                     /* clear TCF 
flag */
        .endm
 
 start:
-       subs    r0, #1                                  /* decrement count for 
DLR */
-       subs    r1, #1                                  /* page size mask and 
for DLR */
-       movs    r4, r3                                  /* copy base address */
-       adds    r4, #QSPI_DR                    /* QSPI DR address */
-       adr             r5, buffer                              /* buffer start 
address */
-       movs    r6, #0                                  /* one byte per default 
*/
-       ldr             r7, [r3, #QSPI_CR]              /* get QSPI CR register 
*/
-       lsrs    r7, #(QSPI_DUAL_FLASH+1)        /* dual bit into carry */
-       bcc             wip_loop                                /* skip if 
single */
-       adds    r6, #1                                  /* two bytes for dual */
+       subs    r0, #1                                          /* decrement 
count for DLR */
+       subs    r1, #1                                          /* page size 
mask and for DLR */
+       ldr             r4, rp                                          /* load 
rp */
+       ldr             r6, [r3, #QSPI_CR]                      /* get QSPI_CR 
register */
+       lsls    r6, r6, #(31-QSPI_DUAL_FLASH)   /* clear higher order bits */
+       lsrs    r6, r6, #31                                     /* DUAL_FLASH 
bit into bit 0 */
+
+abort:
+       movs    r5, #(1<<QSPI_ABORT)            /* abort bit mask */
+       ldr             r7, [r3, #QSPI_CR]                      /* get QSPI_CR 
register */
+       orrs    r7,     r5                                              /* set 
abort bit */
+       str             r7, [r3, #QSPI_CR]                      /* store new CR 
register */
+       movs    r5, #QSPI_DR                            /* load QSPI_DR address 
offset */
 
 wip_loop:
        wait_busy
-       str             r6, [r3, #QSPI_DLR]             /* one or two bytes */
-       ldr             r7, ccr_read_status             /* CCR for status read 
*/
-       str             r7, [r3, #QSPI_CCR]             /* initiate status read 
*/
-       wait_fifo
-       ldrb    r7, [r4, #0]                    /* get first status register */
-       lsrs    r7, #(SPIFLASH_WIP+1)   /* if first flash busy, */
-       bcs             wip_loop                                /* then poll 
again */
-       tst             r6, r6                                  /* dual flash? 
*/
-       beq             write_enable                    /* no, then ok */
-       wait_fifo
-       ldrb    r7, [r4, #0]                    /* get second status register */
-       lsrs    r7, #(SPIFLASH_WIP+1)   /* if second flash busy, */
-       bcs             wip_loop                                /* then poll 
again */
+       str             r6, [r3, #QSPI_DLR]                     /* one or two 
(for dual) bytes */
+       ldr             r7, ccr_read_status                     /* CCR for 
status read */
+       str             r7, [r3, #QSPI_CCR]                     /* initiate 
status read */
+       ldr             r7, [r3, #QSPI_SR]                      /* delay for 
fifo startup */
+       ldrb    r7, [r3, r5]                            /* get first status 
register */
+       lsrs    r7, r7, #(SPIFLASH_WIP+1)       /* if first flash busy, */
+       bcs             abort                                           /* then 
poll again */
+       tst             r6, r6                                          /* dual 
mode ? */
+       beq             write_enable                            /* not dual, 
then ok */
+       ldrb    r7, [r3, r5]                            /* get second status 
register */
+       lsrs    r7, r7, #(SPIFLASH_WIP+1)       /* if second flash busy, */
+       bcs             abort                                           /* then 
poll again */
 
 write_enable:
+       tst             r0, r0                                          /* test 
residual count */
+       bmi             exit                                            /* if 
negative, then finished */
        wait_busy
-       ldr             r7, ccr_write_enable    /* CCR for write enable */
-       str             r7, [r3, #QSPI_CCR]             /* initiate write 
enable */
-
-is_enabled:
-       wait_busy
-       str             r6, [r3, #QSPI_DLR]             /* one or two bytes */
-       ldr             r7, ccr_read_status             /* CCR for status read 
*/
-       str             r7, [r3, #QSPI_CCR]             /* initiate status read 
*/
-       wait_fifo
-       ldrb    r7, [r4, #0]                    /* get first status register */
-       lsrs    r7, #(SPIFLASH_WEL+1)   /* if first flash */
-       bcc             error                                   /* not enabled, 
then error */
-       tst             r6, r6                                  /* dual flash? 
*/
-       beq             busy_loop                               /* no, then ok 
*/
-       wait_fifo
-       ldrb    r7, [r4, #0]                    /* get second status register */
-       lsrs    r7, #(SPIFLASH_WEL+1)   /* if second flash */
-       bcc             error                                   /* not enabled, 
then error */
-
-busy_loop:
+       ldr             r7, ccr_write_enable            /* CCR for write enable 
*/
+       str             r7, [r3, #QSPI_CCR]                     /* initiate 
write enable */
        wait_busy
-       cmp             r0, r1                                  /* if count > 
page size */
-       bhi             page_write                              /* then write 
one page only */
-       str             r0, [r3, #QSPI_DLR]             /* remaining count in 
DLR register */
-       b               start_write
-
-page_write:
-       str             r1, [r3, #QSPI_DLR]             /* page size in DLR 
register */
+       str             r6, [r3, #QSPI_DLR]                     /* one or two 
(for dual) bytes */
+       ldr             r7, ccr_read_status                     /* CCR for 
status read */
+       str             r7, [r3, #QSPI_CCR]                     /* initiate 
status read */
+       ldr             r7, [r3, #QSPI_SR]                      /* delay for 
fifo startup */
+       ldrb    r7, [r3, r5]                            /* get first status 
register */
+       lsrs    r7, r7, #(SPIFLASH_WEL+1)       /* if first flash not */
+       bcc             error                                           /* 
write enabled, then error */
+       tst             r6, r6                                          /* dual 
mode ? */
+       beq             start_write                                     /* not 
dual, then ok */
+       ldrb    r7, [r3, r5]                            /* get second status 
register */
+       lsrs    r7, r7, #(SPIFLASH_WEL+1)       /* if second flash not */
+       bcc             error                                           /* 
write enabled, then error */
 
 start_write:
-       ldr             r7, ccr_page_write              /* CCR for page write */
-       str             r7, [r3, #QSPI_CCR]             /* initiate transfer */
-       str             r2, [r3, #QSPI_AR]              /* store SPI start 
address */
+       mov             r7, r0                                          /* get 
remaining count */
+       cmp             r0, r1                                          /* if 
count <= page size */
+       bls             write_dlr                                       /* then 
write all remaining */
+       mov             r7, r1                                          /* else 
exactly one page */
+write_dlr:
+       str             r7, [r3, #QSPI_DLR]                     /* size-1 in 
DLR register */
+       ldr             r7, ccr_page_write                      /* CCR for page 
write */
+       str             r7, [r3, #QSPI_CCR]                     /* initiate 
transfer */
+       str             r2, [r3, #QSPI_AR]                      /* store SPI 
start address */
 
 write_loop:
-       wait_fifo
-       ldrb    r7,[r5, #0]                             /* load and */
-       strb    r7,[r4, #0]                             /* store next byte */
-       adds    r5, #1                                  /* increment buffer ptr 
*/
-       adds    r2, #1                                  /* increment address */
-       subs    r0, #1                                  /* decrement count */
-       bmi             page_end                                /* stop if no 
data left */
-       tst             r2, r1                                  /* page end ? */
-       bne             write_loop                              /* if not, then 
next byte */
-
+       ldr             r7, wp                                          /* get 
wp */
+       cmp             r7, #0                                          /* if 
wp equals 0 */
+       beq             exit                                            /* then 
abort */
+       cmp             r4, r7                                          /* 
check if fifo empty */
+       beq             write_loop                                      /* wait 
till not empty */
+       ldrb    r7, [r4, #0]                            /* read next byte */
+       strb    r7, [r3, r5]                            /* write next byte to 
DR */
+       adds    r2, #1                                          /* increment 
address */
+       adds    r4, #1                                          /* increment 
internal rp */
+       cmp             r4, r9                                          /* 
internal rp beyond end? */
+       blo             write_loop1                                     /* if 
no, the ok */
+       mov             r4, r8                                          /* else 
wrap around */
+write_loop1:
+       subs    r0, #1                                          /* decrement 
count */
+       bmi             page_end                                        /* stop 
if no data left */
+       tst             r2, r1                                          /* page 
end ? */
+       bne             write_loop                                      /* if 
not, then next byte */
 page_end:
-       ldr             r7, [r3, #QSPI_SR]              /* load status */
-       lsrs    r7, r7, #(QSPI_TCF+1)   /* shift TCF into C */
-       bcc             page_end                                /* wait till 
TCF set */
-       movs    r0, r0                                  /* test residual count 
*/
-       bpl             wip_loop                                /* if 
non-negative, then next page */
-       adds    r0, #1                                  /* correct count */
-       b               exit
+       ldr             r7, [r3, #QSPI_SR]                      /* load status 
*/
+       lsrs    r7, r7, #(QSPI_TCF+1)           /* shift TCF into C */
+       bcc             page_end                                        /* wait 
till TCF set */
+       adr             r7, rp                                          /* get 
address of rp */
+       str             r4, [r7, #0]                            /* store 
updated rp */
+
+       movs    r7, r1                                          /* one 
iteration per byte */
+wait:
+       subs    r7, #1                                          /* short delay 
loop */
+       bne             wait                                            /* 
before testing WIP flag */
+       b               wip_loop                                        /* then 
next page */
 
 error:
-       movs    r0, #0
-       subs    r0, #1                                  /* return 0xFFFFFFFF 
for error */
-
+       movs    r0, #0                                          /* return 
0xFFFFFFFF */
+       subs    r0, #2                                          /* for error */
 exit:
-       .align  2                                               /* align to 
word, bkpt is 4 words */
-       bkpt    #0                                              /* before code 
end for exit_point */
-       .align  2                                               /* align to 
word */
+       adds    r0, #1                                          /* correct 
count */
+       movs    r6, #(1<<QSPI_ABORT)            /* abort bit mask */
+       ldr             r7, [r3, #QSPI_CR]                      /* get QSPI CR 
register */
+       orrs    r7,     r6                                              /* set 
abort bit */
+       str             r7, [r3, #QSPI_CR]                      /* store new CR 
register */
+
+       .align  2                                                       /* 
align to word, bkpt is 4 words */
+       bkpt    #0                                                      /* 
before code end for exit_point */
+       .align  2                                                       /* 
align to word */
 
 ccr_read_status:
-       .space  4                                               /* QSPI_CCR 
value for READ_STATUS command */
+       .space  4                                                       /* 
QSPI_CCR value for READ_STATUS command */
 
 ccr_write_enable:
-       .space  4                                               /* QSPI_CCR 
value for WRITE_ENABLE command */
+       .space  4                                                       /* 
QSPI_CCR value for WRITE_ENABLE command */
 
 ccr_page_write:
-       .space  4                                               /* QSPI_CCR 
value for PAGE_WRITE command */
+       .space  4                                                       /* 
QSPI_CCR value for PAGE_WRITE command */
+
+       .equ wp, .                                                      /* wp, 
uint32_t */
+
+       .equ rp, wp + 4                                         /* rp, uint32_t 
*/
 
-buffer:                                                                /* 
buffer follows right away */
+       .equ buffer, rp + 4                                     /* buffer 
follows right away */
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 06b555b..057587a 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -4920,7 +4920,7 @@ quite board specific (that's why booting from this memory 
is not possible) and
 the flash driver infers all parameters from current controller register values.
 
 Normal OpenOCD commands like @command{mdw} can be used to display
-the flash content, but only after proper controller initialzation.
+the flash content, but only after proper controller initialization.
 
 @example
 flash bank $_FLASHNAME stmqspi 0x90000000 0 0 0 $_TARGETNAME
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index 6d15755..a8416b6 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -44,6 +44,7 @@ NOR_DRIVERS = \
        %D%/spi.c \
        %D%/stmsmi.c \
        %D%/stmqspi.c \
+       %D%/stellaris.c \
        %D%/stm32f1x.c \
        %D%/stm32f2x.c \
        %D%/stm32lx.c \
diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c
index 6501fbc..48acbc4 100644
--- a/src/flash/nor/spi.c
+++ b/src/flash/nor/spi.c
@@ -67,6 +67,7 @@ const struct flash_device flash_devices[] = {
        FLASH_ID("mac 25l1605",    0xd8, 0xc7, 0x001520c2, 0x100, 0x10000, 
0x200000),
        FLASH_ID("mac 25l3205",    0xd8, 0xc7, 0x001620c2, 0x100, 0x10000, 
0x400000),
        FLASH_ID("mac 25l6405",    0xd8, 0xc7, 0x001720c2, 0x100, 0x10000, 
0x800000),
+       FLASH_ID("mac 25l51245",   0xd8, 0xc7, 0x001a20c2, 0x100, 0x10000, 
0x4000000),
        FLASH_ID("micron n25q064", 0xd8, 0xc7, 0x0017ba20, 0x100, 0x10000, 
0x800000),
        FLASH_ID("micron n25q128", 0xd8, 0xc7, 0x0018ba20, 0x100, 0x10000, 
0x1000000),
        FLASH_ID("win w25q80bv",   0xd8, 0xc7, 0x001440ef, 0x100, 0x10000, 
0x100000),
diff --git a/src/flash/nor/stmqspi.c b/src/flash/nor/stmqspi.c
index 234ac15..1883d8b 100644
--- a/src/flash/nor/stmqspi.c
+++ b/src/flash/nor/stmqspi.c
@@ -166,7 +166,10 @@ struct stmqspi_target {
 
 static const struct stmqspi_target target_devices[] = {
        /* name,                                device_id, qspi_base,   io_base 
*/
-       { "stm32l4x6",                  0x415,  0x90000000,     0xA0001000 },
+       { "stm32l431_433_443",  0x435,  0x90000000,     0xA0001000 },
+       { "stm32l4x1_4x5_4x6",  0x415,  0x90000000,     0xA0001000 },
+       { "stm32f412",                  0x441,  0x90000000,     0xA0001000 },
+       { "stm32f413_423",              0x463,  0x90000000,     0xA0001000 },
        { "stm32f446",                  0x421,  0x90000000,     0xA0001000 },
        { "stm32f469_479",              0x434,  0x90000000,     0xA0001000 },
        { "stm32f74x_75x",              0x449,  0x90000000,     0xA0001000 },
@@ -291,7 +294,7 @@ static int wait_till_ready(struct flash_bank *bank, int 
timeout)
 
                if ((status & (((1<<SPIFLASH_WIP)<<8) || (1<<SPIFLASH_WIP))) == 
0)
                        return ERROR_OK;
-               alive_sleep(1);
+               alive_sleep(25);
        } while (timeval_ms() < endtime);
 
        LOG_ERROR("timeout");
@@ -334,6 +337,7 @@ static int qspi_write_enable(struct flash_bank *bank)
                LOG_ERROR("Cannot enable write to flash2. Status=0x%08" PRIx32, 
status);
                return ERROR_FAIL;
        }
+
        return ERROR_OK;
 }
 
@@ -344,7 +348,7 @@ COMMAND_HANDLER(stmqspi_handle_mass_erase_command)
        struct stmqspi_flash_bank *stmqspi_info;
        struct duration bench;
        uint32_t io_base, status;
-       int retval, sector, dual;
+       int retval, sector;
 
        LOG_DEBUG("%s", __func__);
 
@@ -388,21 +392,6 @@ COMMAND_HANDLER(stmqspi_handle_mass_erase_command)
        if (retval != ERROR_OK)
                return retval;
 
-       dual = (stmqspi_info->dual_mask & (1<<QSPI_DUAL_FLASH)) ? 1 : 0;
-
-       /* Clear block protect bits */
-       QSPI_WRITE_REG(QSPI_CCR, QSPI_CCR_WRITE_STATUS);
-       QSPI_WRITE_REG(QSPI_DLR, dual);
-       QSPI_WRITE_REG(QSPI_DR, (1<<SPIFLASH_WEL));
-       if (dual)
-               QSPI_WRITE_REG(QSPI_DR, (1<<SPIFLASH_WEL));
-
-       /* Wait for busy to be cleared */
-       QSPI_POLL_BUSY(QSPI_PROBE_TIMEOUT);
-
-       /* clear transmit finished flag */
-       QSPI_CLEAR_TCF();
-
        retval = qspi_write_enable(bank);
        if (retval != ERROR_OK)
                return retval;
@@ -482,7 +471,7 @@ static int qspi_erase_sector(struct flash_bank *bank, int 
sector)
        retval = wait_till_ready(bank, QSPI_MAX_TIMEOUT);
 
        /* erasure takes a long time, so some sort of progress message is a 
good idea */
-       LOG_USER("sector %4d erased", sector);
+       LOG_DEBUG("sector %4d erased", sector);
 
        /* Switch to memory mapped mode before return to prompt */
        QSPI_SET_MM_MODE();
@@ -532,6 +521,9 @@ static int stmqspi_erase(struct flash_bank *bank, int 
first, int last)
                keep_alive();
        }
 
+       if (retval != ERROR_OK)
+               LOG_ERROR("Flash sector_erase failed on sector %d", sector);
+
        return retval;
 }
 
@@ -545,64 +537,134 @@ static int stmqspi_protect(struct flash_bank *bank, int 
set,
        return ERROR_OK;
 }
 
-static int qspi_write_buffer(struct flash_bank *bank, struct working_area 
*write_algorithm,
-       const uint32_t code_len, const uint32_t flash_offset, const uint32_t 
page_size,
-       uint32_t count, const uint8_t *buffer)
+static int qspi_write_block(struct flash_bank *bank, const uint8_t *buffer,
+               uint32_t offset, uint32_t count)
 {
        struct target *target = bank->target;
        struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
        uint32_t io_base = stmqspi_info->io_base;
-       struct reg_param reg_params[4];
+       struct reg_param reg_params[6];
        struct armv7m_algorithm armv7m_info;
+       struct working_area *write_algorithm;
+       uint32_t page_size, fifo_start, fifo_size, buffer_size;
        uint32_t exit_point, remaining;
-       int retval = ERROR_OK;
+       int dual, retval = ERROR_OK;
 
        LOG_DEBUG("%s: offset=0x%08" PRIx32 " len=0x%08" PRIx32,
-               __func__, flash_offset, count);
+               __func__, offset, count);
 
-       /* after breakpoint instruction (halfword) one nop (halfword) and
-        * 3 words follow till end of code, that makes exactly 4 words */
-       exit_point = write_algorithm->address + code_len - 4 * sizeof(uint32_t);
-       target_write_buffer(target, write_algorithm->address + code_len,
-               count, buffer);
+       /* see contrib/loaders/flash/stmqspi.S for src */
+       static const uint8_t stmqspi_flash_write_code[] = {
+               0x01, 0x38, 0x01, 0x39, 0x32, 0x4c, 0x1e, 0x68, 0x76, 0x06, 
0xf6, 0x0f,
+               0x02, 0x25, 0x1f, 0x68, 0x2f, 0x43, 0x1f, 0x60, 0x20, 0x25, 
0x9f, 0x68,
+               0xbf, 0x09, 0xfc, 0xd2, 0x02, 0x27, 0xdf, 0x60, 0x1e, 0x61, 
0x27, 0x4f,
+               0x5f, 0x61, 0x9f, 0x68, 0x5f, 0x5d, 0x7f, 0x08, 0xee, 0xd2, 
0x36, 0x42,
+               0x02, 0xd0, 0x5f, 0x5d, 0x7f, 0x08, 0xe9, 0xd2, 0x00, 0x42, 
0x3a, 0xd4,
+               0x9f, 0x68, 0xbf, 0x09, 0xfc, 0xd2, 0x02, 0x27, 0xdf, 0x60, 
0x1f, 0x4f,
+               0x5f, 0x61, 0x9f, 0x68, 0xbf, 0x09, 0xfc, 0xd2, 0x02, 0x27, 
0xdf, 0x60,
+               0x1e, 0x61, 0x1a, 0x4f, 0x5f, 0x61, 0x9f, 0x68, 0x5f, 0x5d, 
0xbf, 0x08,
+               0x25, 0xd3, 0x36, 0x42, 0x02, 0xd0, 0x5f, 0x5d, 0xbf, 0x08, 
0x20, 0xd3,
+               0x07, 0x46, 0x88, 0x42, 0x00, 0xd9, 0x0f, 0x46, 0x1f, 0x61, 
0x14, 0x4f,
+               0x5f, 0x61, 0x9a, 0x61, 0x13, 0x4f, 0x00, 0x2f, 0x17, 0xd0, 
0xbc, 0x42,
+               0xfa, 0xd0, 0x27, 0x78, 0x5f, 0x55, 0x01, 0x32, 0x01, 0x34, 
0x4c, 0x45,
+               0x00, 0xd3, 0x44, 0x46, 0x01, 0x38, 0x01, 0xd4, 0x0a, 0x42, 
0xef, 0xd1,
+               0x9f, 0x68, 0xbf, 0x08, 0xfc, 0xd3, 0x0b, 0xa7, 0x3c, 0x60, 
0x0f, 0x00,
+               0x01, 0x3f, 0xfd, 0xd1, 0xb3, 0xe7, 0x00, 0x20, 0x02, 0x38, 
0x01, 0x30,
+               0x02, 0x26, 0x1f, 0x68, 0x37, 0x43, 0x1f, 0x60, 0x00, 0xbe, 
0xc0, 0x46,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00
+       };
+
+       /* This will overlay the last 3 words of stmqspi_flash_write_code in 
target */
+       uint32_t ccr_buffer[] = {
+               h_to_le_32(QSPI_CCR_READ_STATUS),
+               h_to_le_32(QSPI_CCR_WRITE_ENABLE),
+               h_to_le_32(QSPI_CCR_PAGE_WRITE),
+       };
 
-       init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* count (in), 
count (out) */
+       /* memory buffer, we assume sectorsize to be a power of 2 times 
page_size */
+       dual = (stmqspi_info->dual_mask & (1<<QSPI_DUAL_FLASH)) ? 1 : 0;
+       page_size = stmqspi_info->dev->pagesize << dual;
+       fifo_size = stmqspi_info->dev->sectorsize << dual;
+       while (buffer_size = sizeof(stmqspi_flash_write_code) + 2 * 
sizeof(uint32_t) + fifo_size,
+                       target_alloc_working_area_try(target, buffer_size, 
&write_algorithm) != ERROR_OK) {
+               fifo_size /= 2;
+               if (fifo_size < page_size) {
+                       /* we already allocated the writing code, but failed to 
get a
+                        * buffer, free the algorithm */
+                       target_free_working_area(target, write_algorithm);
+
+                       LOG_WARNING("not enough working area, can't do QSPI 
page writes");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
+       };
+
+       /* prepare flash write code, excluding ccr_buffer */
+       retval = target_write_buffer(target, write_algorithm->address,
+               sizeof(stmqspi_flash_write_code) - sizeof(ccr_buffer),
+               stmqspi_flash_write_code);
+       if (retval != ERROR_OK)
+               goto err;
+
+       /* prepare QSPI_CCR register values */
+       retval = target_write_buffer(target, write_algorithm->address
+               + sizeof(stmqspi_flash_write_code) - sizeof(ccr_buffer),
+               sizeof(ccr_buffer), (uint8_t *) ccr_buffer);
+       if (retval != ERROR_OK)
+               goto err;
+
+       /* target buffer starts right after flash_write_code, i. e.
+        * wp and rp are implicitly included in buffer!!! */
+       fifo_start = write_algorithm->address + sizeof(stmqspi_flash_write_code)
+               + 2 * sizeof(uint32_t);
+
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* count (in), 
status (out) */
        init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);    /* page_size */
-       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);    /* offset into 
flash address */
+       init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT); /* offset into 
flash address */
        init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);    /* QSPI io_base 
*/
+       init_reg_param(&reg_params[4], "r8", 32, PARAM_OUT);    /* fifo start */
+       init_reg_param(&reg_params[5], "r9", 32, PARAM_OUT);    /* fifo end + 1 
*/
 
        buf_set_u32(reg_params[0].value, 0, 32, count);
        buf_set_u32(reg_params[1].value, 0, 32, page_size);
-       buf_set_u32(reg_params[2].value, 0, 32, flash_offset);
+       buf_set_u32(reg_params[2].value, 0, 32, offset);
        buf_set_u32(reg_params[3].value, 0, 32, io_base);
+       buf_set_u32(reg_params[4].value, 0, 32, fifo_start);
+       buf_set_u32(reg_params[5].value, 0, 32, fifo_start + fifo_size);
 
        armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
        armv7m_info.core_mode = ARM_MODE_THREAD;
 
-       retval = target_start_algorithm(target, 0, NULL,
-               sizeof(reg_params) / sizeof(struct reg_param), reg_params,
-               write_algorithm->address, exit_point, &armv7m_info);
+       /* after breakpoint instruction (halfword) one nop (halfword) and
+        * 3 words follow till end of code, that makes exactly 4 words */
+       exit_point = write_algorithm->address
+               + sizeof(stmqspi_flash_write_code) - 4 * sizeof(uint32_t);
 
-       retval = target_wait_algorithm(target, 0, NULL,
-               sizeof(reg_params) / sizeof(struct reg_param), reg_params,
-               exit_point, QSPI_MAX_TIMEOUT, &armv7m_info);
+       retval = target_run_flash_async_algorithm(target, buffer, count, 1,
+                       0, NULL,
+                       6, reg_params,
+                       write_algorithm->address + 
sizeof(stmqspi_flash_write_code),
+                       fifo_size + 2 * sizeof(uint32_t),
+                       write_algorithm->address, exit_point,
+                       &armv7m_info);
 
        remaining = buf_get_u32(reg_params[0].value, 0, 32);
        if ((retval == ERROR_OK) && remaining)
                retval = ERROR_FLASH_OPERATION_FAILED;
        if (retval != ERROR_OK) {
+               offset = buf_get_u32(reg_params[2].value, 0, 32);
                LOG_ERROR("flash write failed at address 0x%" PRIx32 ", 
remaining 0x%" PRIx32,
-                       flash_offset, remaining);
-       } else {
-               /* programming takes a long time, so some sort of progress 
message is a good idea */
-               LOG_USER("pages %6d to %6d programmed", flash_offset / 
page_size,
-                       (flash_offset + count - 1) / page_size);
+                       offset, remaining);
        }
 
        destroy_reg_param(&reg_params[0]);
        destroy_reg_param(&reg_params[1]);
        destroy_reg_param(&reg_params[2]);
        destroy_reg_param(&reg_params[3]);
+       destroy_reg_param(&reg_params[4]);
+       destroy_reg_param(&reg_params[5]);
+
+err:
+       target_free_working_area(target, write_algorithm);
 
        /* Switch to memory mapped mode before return to prompt */
        QSPI_SET_MM_MODE();
@@ -611,64 +673,31 @@ static int qspi_write_buffer(struct flash_bank *bank, 
struct working_area *write
 }
 
 static int stmqspi_write(struct flash_bank *bank, const uint8_t *buffer,
-       uint32_t flash_offset, uint32_t count)
+       uint32_t offset, uint32_t count)
 {
        struct target *target = bank->target;
        struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
-       struct working_area *write_algorithm;
-       uint32_t io_base = stmqspi_info->io_base;
-       uint32_t cur_count, page_size, buffer_size;
-       int sector;
-       int dual;
-       int retval = ERROR_OK;
-
-       /* see contrib/loaders/flash/stmqspi.S for src */
-       static const uint8_t stmqspi_flash_write_code[] = {
-               0x01, 0x38, 0x01, 0x39, 0x1c, 0x00, 0x20, 0x34, 0x30, 0xa5, 
0x00, 0x26,
-               0x1f, 0x68, 0xff, 0x09, 0x00, 0xd3, 0x01, 0x36, 0x9f, 0x68, 
0xbf, 0x09,
-               0xfc, 0xd2, 0x02, 0x27, 0xdf, 0x60, 0x1e, 0x61, 0x27, 0x4f, 
0x5f, 0x61,
-               0x9f, 0x68, 0xff, 0x08, 0xfc, 0xd3, 0x27, 0x78, 0x7f, 0x08, 
0xf1, 0xd2,
-               0x36, 0x42, 0x05, 0xd0, 0x9f, 0x68, 0xff, 0x08, 0xfc, 0xd3, 
0x27, 0x78,
-               0x7f, 0x08, 0xe9, 0xd2, 0x9f, 0x68, 0xbf, 0x09, 0xfc, 0xd2, 
0x02, 0x27,
-               0xdf, 0x60, 0x1e, 0x4f, 0x5f, 0x61, 0x9f, 0x68, 0xbf, 0x09, 
0xfc, 0xd2,
-               0x02, 0x27, 0xdf, 0x60, 0x1e, 0x61, 0x19, 0x4f, 0x5f, 0x61, 
0x9f, 0x68,
-               0xff, 0x08, 0xfc, 0xd3, 0x27, 0x78, 0xbf, 0x08, 0x26, 0xd3, 
0x36, 0x42,
-               0x05, 0xd0, 0x9f, 0x68, 0xff, 0x08, 0xfc, 0xd3, 0x27, 0x78, 
0xbf, 0x08,
-               0x1e, 0xd3, 0x9f, 0x68, 0xbf, 0x09, 0xfc, 0xd2, 0x02, 0x27, 
0xdf, 0x60,
-               0x88, 0x42, 0x01, 0xd8, 0x18, 0x61, 0x00, 0xe0, 0x19, 0x61, 
0x0e, 0x4f,
-               0x5f, 0x61, 0x9a, 0x61, 0x9f, 0x68, 0xff, 0x08, 0xfc, 0xd3, 
0x2f, 0x78,
-               0x27, 0x70, 0x01, 0x35, 0x01, 0x32, 0x01, 0x38, 0x01, 0xd4, 
0x0a, 0x42,
-               0xf4, 0xd1, 0x9f, 0x68, 0xbf, 0x08, 0xfc, 0xd3, 0x00, 0x00, 
0xaf, 0xd5,
-               0x01, 0x30, 0x01, 0xe0, 0x00, 0x20, 0x01, 0x38, 0x00, 0xbe, 
0xc0, 0x46,
-               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00
-       };
-
-       /* This will overlay the last 3 words of stmqspi_flash_write_code in 
target */
-       uint32_t ccr_buffer[] = {
-               h_to_le_32(QSPI_CCR_READ_STATUS),
-               h_to_le_32(QSPI_CCR_WRITE_ENABLE),
-               h_to_le_32(QSPI_CCR_PAGE_WRITE),
-       };
+       int sector, dual;
 
        LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
-               __func__, flash_offset, count);
+               __func__, offset, count);
 
        if (target->state != TARGET_HALTED) {
                LOG_ERROR("Target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       if (flash_offset + count > stmqspi_info->dev->size_in_bytes) {
-               LOG_WARNING("Write past end of flash. Extra data discarded.");
-               count = stmqspi_info->dev->size_in_bytes - flash_offset;
+       if (offset + count > stmqspi_info->dev->size_in_bytes) {
+               LOG_WARNING("Write beyond end of flash. Extra data discarded.");
+               count = stmqspi_info->dev->size_in_bytes - offset;
        }
 
        /* Check sector protection */
        for (sector = 0; sector < bank->num_sectors; sector++) {
                /* Start offset in or before this sector? */
                /* End offset in or behind this sector? */
-               if ((flash_offset < (bank->sectors[sector].offset + 
bank->sectors[sector].size))
-                       && ((flash_offset + count - 1) >= 
bank->sectors[sector].offset)
+               if ((offset < (bank->sectors[sector].offset + 
bank->sectors[sector].size))
+                       && ((offset + count - 1) >= 
bank->sectors[sector].offset)
                        && bank->sectors[sector].is_protected) {
                        LOG_ERROR("Flash sector %d protected", sector);
                        return ERROR_FAIL;
@@ -676,87 +705,14 @@ static int stmqspi_write(struct flash_bank *bank, const 
uint8_t *buffer,
        }
 
        dual = (stmqspi_info->dual_mask & (1<<QSPI_DUAL_FLASH)) ? 1 : 0;
-       if (dual & ((flash_offset & 1) != 0 || (count & 1) != 0)) {
+       if (dual & ((offset & 1) != 0 || (count & 1) != 0)) {
                LOG_ERROR("For dual-QSPI writes must be two byte aligned: "
                        "%s: address=0x%08" PRIx32 " len=0x%08" PRIx32, 
__func__,
-                       flash_offset, count);
+                       offset, count);
                return ERROR_FAIL;
        }
-       page_size = stmqspi_info->dev->pagesize << dual;
-
-       /* memory buffer, we assume sectorsize to be a power of 2 times 
page_size */
-       buffer_size = stmqspi_info->dev->sectorsize << dual;
-       while (target_alloc_working_area_try(target,
-                       sizeof(stmqspi_flash_write_code) + buffer_size,
-                       &write_algorithm) != ERROR_OK) {
-               buffer_size /= 2;
-               if (buffer_size < page_size) {
-                       /* we already allocated the writing code, but failed to 
get a
-                        * buffer, free the algorithm */
-                       target_free_working_area(target, write_algorithm);
-
-                       LOG_WARNING("not enough working area, can't do QSPI 
page writes");
-                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-               }
-       };
 
-       /* prepare flash write code, excluding ccr_buffer */
-       retval = target_write_buffer(target, write_algorithm->address,
-               sizeof(stmqspi_flash_write_code) - sizeof(ccr_buffer),
-               stmqspi_flash_write_code);
-       if (retval != ERROR_OK)
-               goto err;
-
-       /* prepare QSPI_CCR register values */
-       retval = target_write_buffer(target, write_algorithm->address
-               + sizeof(stmqspi_flash_write_code) - sizeof(ccr_buffer),
-               sizeof(ccr_buffer), (uint8_t *) ccr_buffer);
-       if (retval != ERROR_OK)
-               goto err;
-
-       /* Abort any previous operation */
-       QSPI_WRITE_REG(QSPI_CR, QSPI_READ_REG(QSPI_CR) | (1<<QSPI_ABORT));
-
-       /* buffer head not aligned to page size */
-       if (count > 0 && (flash_offset & (page_size - 1)) != 0) {
-               cur_count = page_size - (flash_offset & (page_size - 1));
-               if (cur_count > count)
-                       cur_count = count;
-               retval = qspi_write_buffer(bank, write_algorithm,
-                       sizeof(stmqspi_flash_write_code), flash_offset,
-                       page_size, cur_count, buffer);
-               if (retval != ERROR_OK)
-                       goto err;
-               flash_offset += cur_count;
-               buffer += cur_count;
-               count -= cur_count;
-       }
-
-       /* central part, aligned to page size */
-       while (count > 0) {
-               /* clip block at buffer_size */
-               if (count > buffer_size)
-                       cur_count = buffer_size;
-               else
-                       cur_count = count;
-
-               retval = qspi_write_buffer(bank, write_algorithm,
-                       sizeof(stmqspi_flash_write_code), flash_offset,
-                       page_size, cur_count, buffer);
-               if (retval != ERROR_OK)
-                       goto err;
-
-               flash_offset += cur_count;
-               buffer += cur_count;
-               count -= cur_count;
-
-               keep_alive();
-       }
-
-err:
-       target_free_working_area(target, write_algorithm);
-
-       return retval;
+       return qspi_write_block(bank, buffer, offset, count);
 }
 
 /* Return ID of flash device(s) */
@@ -773,6 +729,7 @@ static int read_flash_id(struct flash_bank *bank, uint32_t 
*id1, uint32_t *id2)
                return ERROR_TARGET_NOT_HALTED;
        }
 
+       QSPI_WRITE_REG(QSPI_CR, QSPI_READ_REG(QSPI_CR) | (1<<QSPI_ABORT));
        /* poll WIP */
        retval = wait_till_ready(bank, QSPI_PROBE_TIMEOUT);
        if (retval != ERROR_OK)
@@ -788,6 +745,9 @@ static int read_flash_id(struct flash_bank *bank, uint32_t 
*id1, uint32_t *id2)
        QSPI_WRITE_REG(QSPI_CCR, (QSPI_READ_REG(QSPI_CCR) & 0xF0000000) |
           ((QSPI_READ_MODE | QSPI_1LINE_MODE | QSPI_ADDR3 | SPIFLASH_READ_ID) 
& QSPI_NO_ADDR));
 
+       /* Three address bytes, could be dummy for some chips */
+       QSPI_WRITE_REG(QSPI_AR, 0);
+
        /* Poll transmit finished flag */
        QSPI_POLL_TCF(QSPI_CMD_TIMEOUT);
 
@@ -799,26 +759,32 @@ static int read_flash_id(struct flash_bank *bank, 
uint32_t *id1, uint32_t *id2)
                if ((stmqspi_info->dual_mask & ((1<<QSPI_DUAL_FLASH) |
                        (1<<QSPI_FSEL_FLASH))) != (1<<QSPI_FSEL_FLASH)) {
                        *id1 |= (QSPI_READ_REGB(QSPI_DR) << shift);
-                       if (!*id1) {
-                               LOG_ERROR("No response from QSPI flash1");
-                               return ERROR_FAIL;
-                       }
-
                }
                if ((stmqspi_info->dual_mask & ((1<<QSPI_DUAL_FLASH) |
                        (1<<QSPI_FSEL_FLASH))) != 0) {
                        *id2 |= (QSPI_READ_REGB(QSPI_DR) << shift);
-                       if (!*id2) {
-                               LOG_ERROR("No response from QSPI flash2");
-                               return ERROR_FAIL;
-                       }
+               }
+       }
+
+       if ((stmqspi_info->dual_mask & ((1<<QSPI_DUAL_FLASH) |
+               (1<<QSPI_FSEL_FLASH))) != (1<<QSPI_FSEL_FLASH)) {
+               if (!*id1) {
+                       LOG_ERROR("No response from QSPI flash1");
+                       retval = ERROR_FAIL;
+               }
+       }
+       if ((stmqspi_info->dual_mask & ((1<<QSPI_DUAL_FLASH) |
+               (1<<QSPI_FSEL_FLASH))) != 0) {
+               if (!*id2) {
+                       LOG_ERROR("No response from QSPI flash2");
+                       retval = ERROR_FAIL;
                }
        }
 
        /* Switch to memory mapped mode before return to prompt */
        QSPI_SET_MM_MODE();
 
-       return ERROR_OK;
+       return retval;
 }
 
 static int stmqspi_probe(struct flash_bank *bank)
@@ -830,8 +796,7 @@ static int stmqspi_probe(struct flash_bank *bank)
        uint32_t id1 = 0, id2 = 0;
        const struct stmqspi_target *target_device;
        const struct flash_device *p;
-       int dual;
-       int retval;
+       int dual, fsize, retval;
 
        if (stmqspi_info->probed)
                free(bank->sectors);
@@ -849,17 +814,15 @@ static int stmqspi_probe(struct flash_bank *bank)
 
        if (!target_device->name) {
                LOG_ERROR("Device ID 0x%" PRIx32 " is not known as STM QSPI 
capable",
-                               target->tap->idcode);
+                       target->tap->idcode);
                return ERROR_FAIL;
        }
 
-       switch (bank->base - target_device->qspi_base) {
-               case 0*QSPI_BANK_SIZE:
-                       stmqspi_info->bank_num = QSPI_SEL_BANK0;
-                       break;
-               default:
-                       LOG_ERROR("Invalid QSPI base address 0x%" PRIx32, 
bank->base);
-                       return ERROR_FAIL;
+       if (bank->base == target_device->qspi_base) {
+               stmqspi_info->bank_num = QSPI_SEL_BANK0;
+       } else {
+               LOG_ERROR("Invalid QSPI base address 0x%" PRIx32, bank->base);
+               return ERROR_FAIL;
        }
        io_base = target_device->io_base;
        stmqspi_info->io_base = io_base;
@@ -868,8 +831,8 @@ static int stmqspi_probe(struct flash_bank *bank)
        stmqspi_info->dual_mask = QSPI_READ_REG(QSPI_CR);
        /* save current QSPI_CCR value */;
        stmqspi_info->saved_ccr = QSPI_READ_REG(QSPI_CCR);
-       LOG_DEBUG("Valid QSPI on device %s at 0x%" PRIx32 ", QSPI_CR 0x%"
-               PRIx32 ", QSPI_CCR 0x%" PRIx32 ",%s", target_device->name,
+       LOG_DEBUG("Valid QSPI in device %s at 0x%" PRIx32 ", QSPI_CR 0x%"
+               PRIx32 ", QSPI_CCR 0x%" PRIx32 ", %s", target_device->name,
                bank->base, stmqspi_info->dual_mask, stmqspi_info->saved_ccr,
                (QSPI_ADDR_MASK == QSPI_ADDR4) ? "4 byte addr" : " 3 byte 
addr");
 
@@ -886,22 +849,24 @@ static int stmqspi_probe(struct flash_bank *bank)
        for (p = flash_devices; id1 && p->name ; p++) {
                if (p->device_id == id1) {
                        stmqspi_info->dev = p;
-                       LOG_INFO("Found flash1 device \'%s\' (ID 0x%06" PRIx32 
")",
-                               p->name, id1);
+                       LOG_INFO("flash1 \'%s\' id = 0x%06" PRIx32
+                                "\nflash1 size = %lukbytes",
+                                p->name, id1, p->size_in_bytes>>10);
                        break;
                }
        }
 
        if (id1 && !p->name) {
-               LOG_ERROR("Unknown flash1 device (ID 0x%06" PRIx32 ")", id1);
+               LOG_ERROR("Unknown flash1 device id = 0x%06" PRIx32, id1);
                return ERROR_FAIL;
        }
 
        /* identify flash2 */
        for (p = flash_devices; id2 && p->name ; p++) {
                if (p->device_id == id2) {
-                       LOG_INFO("Found flash2 device \'%s\' (ID 0x%06" PRIx32 
")",
-                               p->name, id2);
+                       LOG_INFO("flash2 \'%s\' id = 0x%06" PRIx32
+                                "\nflash2 size = %lukbytes",
+                                p->name, id2, p->size_in_bytes>>10);
 
                        if (!stmqspi_info->dev)
                                stmqspi_info->dev = p;
@@ -920,15 +885,21 @@ static int stmqspi_probe(struct flash_bank *bank)
        }
 
        if (id2 && !p->name) {
-               LOG_ERROR("Unknown flash2 device (ID 0x%06" PRIx32 ")", id2);
+               LOG_ERROR("Unknown flash2 device id = 0x%06" PRIx32, id2);
                return ERROR_FAIL;
        }
 
-       dual = (stmqspi_info->dual_mask & (1<<QSPI_DUAL_FLASH)) ? 1 : 0;
-
        /* Set correct size value */
+       dual = (stmqspi_info->dual_mask & (1<<QSPI_DUAL_FLASH)) ? 1 : 0;
        bank->size = stmqspi_info->dev->size_in_bytes << dual;
 
+       fsize = (QSPI_READ_REG(QSPI_DCR)>>QSPI_FSIZE0) & ((1<<QSPI_FSIZE_LEN) - 
1);
+       LOG_DEBUG("FSIZE = 0x%04x", fsize);
+       if (bank->size != (1U<<(fsize + 1))) {
+               LOG_ERROR("FSIZE field in QSPI_DCR doesn't match actual 
capacity. Initialzation error?");
+               return ERROR_FAIL;
+       }
+
        /* create and fill sectors array */
        bank->num_sectors =
                stmqspi_info->dev->size_in_bytes / 
stmqspi_info->dev->sectorsize;
@@ -942,7 +913,7 @@ static int stmqspi_probe(struct flash_bank *bank)
                sectors[sector].offset = sector * 
(stmqspi_info->dev->sectorsize << dual);
                sectors[sector].size = (stmqspi_info->dev->sectorsize << dual);
                sectors[sector].is_erased = -1;
-               sectors[sector].is_protected = 1;
+               sectors[sector].is_protected = 0;
        }
 
        bank->sectors = sectors;
@@ -954,6 +925,7 @@ static int stmqspi_probe(struct flash_bank *bank)
 static int stmqspi_auto_probe(struct flash_bank *bank)
 {
        struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
+
        if (stmqspi_info->probed)
                return ERROR_OK;
        return stmqspi_probe(bank);
@@ -975,9 +947,8 @@ static int get_stmqspi_info(struct flash_bank *bank, char 
*buf, int buf_size)
                return ERROR_OK;
        }
 
-       snprintf(buf, buf_size, "\nQSPI flash information:"
-               " Device \'%s\' (ID 0x%06" PRIx32 ")\n",
-               stmqspi_info->dev->name, stmqspi_info->dev->device_id);
+       snprintf(buf, buf_size, "\'%s\' %dkbytes id = 0x%06" PRIx32,
+               stmqspi_info->dev->name, bank->size>>10, 
stmqspi_info->dev->device_id);
 
        return ERROR_OK;
 }
@@ -1017,5 +988,4 @@ struct flash_driver stmqspi_flash = {
        .erase_check = default_flash_blank_check,
        .protect_check = stmqspi_protect_check,
        .info = get_stmqspi_info,
-       .usage = "",
 };
diff --git a/src/flash/nor/stmqspi.h b/src/flash/nor/stmqspi.h
index abb34d4..362cfb8 100644
--- a/src/flash/nor/stmqspi.h
+++ b/src/flash/nor/stmqspi.h
@@ -25,6 +25,7 @@
 
 /* register offsets */
 #define QSPI_CR                        (0x00)  /* Control register */
+#define QSPI_DCR               (0x04)  /* Configuration register */
 #define QSPI_SR                        (0x08)  /* Status register */
 #define QSPI_FCR               (0x0C)  /* Flag clear register */
 #define QSPI_DLR               (0x10)  /* Data length register */
@@ -38,6 +39,10 @@
 #define QSPI_DUAL_FLASH                6       /* Dual flash mode */
 #define QSPI_ABORT                     1       /* Abort bit */
 
+/* bits in QSPI_DCR */
+#define QSPI_FSIZE0                    16      /* bottom of FSIZE field */
+#define QSPI_FSIZE_LEN         5       /* width of FSIZE field */
+
 /* bits in QSPI_SR */
 #define QSPI_BUSY                      5       /* Busy flag */
 #define QSPI_FTF                       2       /* FIFO threshold flag */
@@ -48,8 +53,8 @@
 #define QSPI_READ_MODE         0x04000000              /* indirect read mode */
 #define QSPI_MM_MODE           0x0C000000              /* memory mapped mode */
 #define QSPI_1LINE_MODE                0x01000500              /* 1 line for 
address, data */
-#define QSPI_2LINE_MODE                0x02000900              /* 2 lines for 
address, data */
-#define QSPI_4LINE_MODE                0x03000D00              /* 4 lines for 
address, data */
+#define QSPI_2LINE_MODE                0x02000A00              /* 2 lines for 
address, data */
+#define QSPI_4LINE_MODE                0x03000F00              /* 4 lines for 
address, data */
 #define QSPI_NO_DATA           (~0x03000000)   /* no data */
 #define QSPI_NO_ADDR           (~0x00000C00)   /* no address */
 #define QSPI_ADDR3                     0x00002000              /* 3 byte 
address */
diff --git a/tcl/board/stm32f746g-disco_stlink.cfg 
b/tcl/board/stm32f746g-disco_stlink.cfg
index 71afa83..3b2061b 100644
--- a/tcl/board/stm32f746g-disco_stlink.cfg
+++ b/tcl/board/stm32f746g-disco_stlink.cfg
@@ -12,13 +12,13 @@ set WORKAREASIZE 0x40000
 source [find target/stm32f7x.cfg]
 
 $_TARGETNAME configure -event reset-init {
-    # QUADSPI initialization
+       # QUADSPI initialization
 
        mmw 0x40023830 0x000007FF 0     ;# RCC_AHB1ENR |= GPIOA-GPIOK (enable 
clocks)
        mmw 0x40023838 0x00000002 0     ;# RCC_AHB3ENR |= QSPIEN (enable clock)
        sleep 1                                         ;# Wait for clock 
startup
 
-    # PB2: CLK, PB6: BK1_nCS, PD13: BK1_IO3, PE2: BK1_IO2, PD12: BK1_IO1, 
PD11: BK1_IO0
+       # PB2: CLK, PB6: BK1_nCS, PD13: BK1_IO3, PE2: BK1_IO2, PD12: BK1_IO1, 
PD11: BK1_IO0
        mmw 0x40020400 0x00002020 0x00001010    ;# PB6, PB2 alternate
        mmw 0x40020408 0x00003030 0x00000000    ;# high speed
        mmw 0x40020420 0x0A000900 0x05000600    ;# AF10, AF9
@@ -33,6 +33,8 @@ $_TARGETNAME configure -event reset-init {
 
        mww 0xA0001004 0x00170100       ;# QUADSPI_DCR: FSIZE=0x17, CSHT=0x01, 
CKMODE=0
        mww 0xA0001000 0x01500318       ;# QUADSPI_CR: PRESCALER=1, APMS=1, 
FTHRES=3, SSHIFT=1, TCEN=1
-       mww 0xA0001014 0x0D002503       ;# QUADSPI_CCR: FMODE=0x3, DMODE=0x1, 
DCYC=0x0, ADSIZE=0x3, ADMODE=0x1, IMODE=0x1
        mmw 0xA0001000 0x00000001 0     ;# QUADSPI_CR: EN=1
+
+       # memory-mapped read mode with 3-byte addresses
+       mww 0xA0001014 0x0D002503       ;# QUADSPI_CCR: FMODE=0x3, DMODE=0x1, 
DCYC=0x0, ADSIZE=0x3, ADMODE=0x1, IMODE=0x1, INSTR=READ
 }
diff --git a/tcl/board/stm32f769i-disco_stlink.cfg 
b/tcl/board/stm32f769i-disco_stlink.cfg
index 3cef71c..97fa1fd 100644
--- a/tcl/board/stm32f769i-disco_stlink.cfg
+++ b/tcl/board/stm32f769i-disco_stlink.cfg
@@ -12,20 +12,20 @@ set WORKAREASIZE 0x40000
 source [find target/stm32f7x.cfg]
 
 $_TARGETNAME configure -event reset-init {
-    # QUADSPI initialization
+       # QUADSPI initialization
 
        mmw 0x40023830 0x000007FF 0     ;# RCC_AHB1ENR |= GPIOA-GPIOK (enable 
clocks)
        mmw 0x40023838 0x00000002 0     ;# RCC_AHB3ENR |= QSPIEN (enable clock)
        sleep 1                                         ;# Wait for clock 
startup
 
-    # PB2: CLK, PB6: BK1_nCS, PD13: BK1_IO3, PE2: BK1_IO2, PC10: BK1_IO1, PC9: 
BK1_IO0
+       # PB2: CLK, PB6: BK1_nCS, PD13: BK1_IO3, PE2: BK1_IO2, PC10: BK1_IO1, 
PC9: BK1_IO0
        mmw 0x40020400 0x00002020 0x00001010    ;# PB6, PB2 alternate
        mmw 0x40020408 0x00003030 0x00000000    ;# high speed
        mmw 0x40020420 0x0A000900 0x05000600    ;# AF10, AF9
 
        mmw 0x40020800 0x00280000 0x00140000    ;# PC10, PC9 alternate
        mmw 0x40020808 0x003C0000 0x00000000    ;# high speed
-       mmw 0x40020424 0x00000990 0x00000660    ;# AF9, AF9
+       mmw 0x40020824 0x00000990 0x00000660    ;# AF9, AF9
 
        mmw 0x40020C00 0x08000000 0x04000000    ;# PD13 alternate
        mmw 0x40020C08 0x0C000000 0x00000000    ;# high speed
@@ -35,8 +35,18 @@ $_TARGETNAME configure -event reset-init {
        mmw 0x40021008 0x00000030 0x00000000    ;# high speed
        mmw 0x40021020 0x00000900 0x00000600    ;# AF9
 
-       mww 0xA0001004 0x00170100       ;# QUADSPI_DCR: FSIZE=0x17, CSHT=0x01, 
CKMODE=0
        mww 0xA0001000 0x01500318       ;# QUADSPI_CR: PRESCALER=1, APMS=1, 
FTHRES=3, SSHIFT=1, TCEN=1
-       mww 0xA0001014 0x0D002503       ;# QUADSPI_CCR: FMODE=0x3, DMODE=0x1, 
DCYC=0x0, ADSIZE=0x3, ADMODE=0x1, IMODE=0x1
+       mww 0xA0001004 0x00190100       ;# QUADSPI_DCR: FSIZE=0x19, CSHT=0x01, 
CKMODE=0
        mmw 0xA0001000 0x00000001 0     ;# QUADSPI_CR: EN=1
+
+       # 1-line spi mode
+       mww 0xA0001014 0x000003F5       ;# QUADSPI_CCR: FMODE=0x0, DMODE=0x0, 
DCYC=0x0, ADSIZE=0x0, ADMODE=0x0, IMODE=0x3, INSTR=RSTQIO
+       sleep 1
+
+       # 4-byte address mode
+       mww 0xA0001014 0x000001B7       ;# QUADSPI_CCR: FMODE=0x0, DMODE=0x0, 
DCYC=0x0, ADSIZE=0x0, ADMODE=0x0, IMODE=0x1, INSTR=EN4B
+       sleep 1
+
+       # memory-mapped read mode with 4-byte addresses
+       mww 0xA0001014 0x0D003503       ;# QUADSPI_CCR: FMODE=0x3, DMODE=0x1, 
DCYC=0x0, ADSIZE=0x3, ADMODE=0x1, IMODE=0x1, INSTR=READ
 }
diff --git a/tcl/board/stm32l476g-disco_stlink.cfg 
b/tcl/board/stm32l476g-disco_stlink.cfg
new file mode 100644
index 0000000..4c8b07a
--- /dev/null
+++ b/tcl/board/stm32l476g-disco_stlink.cfg
@@ -0,0 +1,32 @@
+# This is an STM32L476G discovery board with a single STM32L476VGT6 chip.
+# http://www.st.com/en/evaluation-tools/32l476gdiscovery.html
+
+# This is for using the onboard STLINK/V2-1
+source [find interface/stlink-v2-1.cfg]
+
+transport select hla_swd
+
+# increase working area to 96KB
+set WORKAREASIZE 0x18000
+
+source [find target/stm32l4x.cfg]
+
+$_TARGETNAME configure -event reset-init {
+
+       # QUADSPI initialization
+       mmw 0x4002104C 0x000000FF 0             ;# RCC_AHB2ENR |= GPIOA-GPIOK 
(enable clocks)
+       mmw 0x40021050 0x00000100 0             ;# RCC_AHB3ENR |= QSPIEN 
(enable clock)
+       sleep 1                                                 ;# Wait for 
clock startup
+
+       # PE10: CLK, PE11: BK1_nCS, PE15: BK1_IO3, PE14: BK1_IO2, PE13: 
BK1_IO1, PE12: BK1_IO0
+       mmw 0x48001000 0xAAA00000 0x55500000    ;# PB15-10 alternate
+       mmw 0x48001008 0xFFF00000 0x00000000    ;# high speed
+       mmw 0x48001024 0xAAAAAA00 0x55555500    ;# AF10, AF10, AF10, AF10, 
AF10, AF10
+
+       mww 0xA0001004 0x00170100       ;# QUADSPI_DCR: FSIZE=0x17, CSHT=0x01, 
CKMODE=0
+       mww 0xA0001000 0x01500318       ;# QUADSPI_CR: PRESCALER=1, APMS=1, 
FTHRES=3, SSHIFT=1, TCEN=1
+       mmw 0xA0001000 0x00000001 0     ;# QUADSPI_CR: EN=1
+
+       # memory-mapped read mode with 3-byte addresses
+       mww 0xA0001014 0x0D002503       ;# QUADSPI_CCR: FMODE=0x3, DMODE=0x1, 
DCYC=0x0, ADSIZE=0x3, ADMODE=0x1, IMODE=0x1, INSTR=READ
+}
diff --git a/tcl/target/stm32f7x.cfg b/tcl/target/stm32f7x.cfg
index 05470d4..b4cb86b 100755
--- a/tcl/target/stm32f7x.cfg
+++ b/tcl/target/stm32f7x.cfg
@@ -58,6 +58,9 @@ $_TARGETNAME configure -work-area-phys 0x20000000 
-work-area-size $_WORKAREASIZE
 set _FLASHNAME $_CHIPNAME.flash
 flash bank $_FLASHNAME stm32f2x 0 0 0 0 $_TARGETNAME
 
+set _QSPINAME $_CHIPNAME.qspi
+flash bank $_QSPINAME stmqspi 0x90000000 0 0 0 $_TARGETNAME
+
 # adapter speed should be <= F_CPU/6. F_CPU after reset is 16MHz, so use 
F_JTAG = 2MHz
 adapter_khz 2000
 
diff --git a/tcl/target/stm32l4x.cfg b/tcl/target/stm32l4x.cfg
index 9cad7c4..eccd938 100644
--- a/tcl/target/stm32l4x.cfg
+++ b/tcl/target/stm32l4x.cfg
@@ -49,6 +49,9 @@ $_TARGETNAME configure -work-area-phys 0x20000000 
-work-area-size $_WORKAREASIZE
 set _FLASHNAME $_CHIPNAME.flash
 flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
 
+set _QSPINAME $_CHIPNAME.qspi
+flash bank $_QSPINAME stmqspi 0x90000000 0 0 0 $_TARGETNAME
+
 # Common knowledges tells JTAG speed should be <= F_CPU/6.
 # F_CPU after reset is MSI 4MHz, so use F_JTAG = 500 kHz to stay on
 # the safe side.

-- 

------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today.http://sdm.link/intel
_______________________________________________
OpenOCD-devel mailing list
OpenOCD-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to