3af82d4d8aae9df05635af2a4ab7f9a003248f4d
[fw/openocd] / contrib / loaders / flash / stmqspi / stmoctospi_erase_check.S
1 /***************************************************************************
2  *   Copyright (C) 2019 by Andreas Bolsch                                  *
3  *   andreas.bolsch@mni.thm.de                                             *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
17  ***************************************************************************/
18
19         .text
20         .syntax unified
21         .cpu cortex-m0
22         .thumb
23         .thumb_func
24
25 /* Params:
26  * r0 - sector count
27  * r1 - QSPI io_base
28
29  * Clobbered:
30  * r2 - r7 tmp */
31
32 #include "../../../../src/flash/nor/stmqspi.h"
33
34 #define OCTOSPI_CCR_CCR                                 (OCTOSPI_CCR - OCTOSPI_CCR)
35 #define OCTOSPI_TCR_CCR                                 (OCTOSPI_TCR - OCTOSPI_CCR)
36 #define OCTOSPI_IR_CCR                                  (OCTOSPI_IR - OCTOSPI_CCR)
37
38         .macro  octospi_abort
39         movs    r5, #(1<<SPI_ABORT)                     /* abort bit mask */
40         ldr             r7, [r1, #OCTOSPI_CR]           /* get OCTOSPI_CR register */
41         orrs    r7, r7, r5                                      /* set abort bit */
42         str             r7, [r1, #OCTOSPI_CR]           /* store new CR register */
43         .endm
44
45         .macro  wait_busy
46 0:
47         ldr             r7, [r1, #OCTOSPI_SR]           /* load status */
48         lsrs    r7, r7, #(SPI_BUSY+1)           /* shift BUSY into C */
49         bcs             0b                                                      /* loop until BUSY cleared */
50         movs    r7, #(1<<SPI_TCF)                       /* TCF bitmask */
51         str             r7, [r1, #OCTOSPI_FCR]          /* clear TCF flag */
52         .endm
53
54 start:
55         adr             r2, buffer                                      /* pointer to start of buffer */
56         movs    r3, #OCTOSPI_DR                         /* load OCTOSPI_DR address offset */
57         adds    r3, r3, r1                                      /* address of OCTOSPI_DR */
58 sector_start:
59         octospi_abort                                           /* start in clean state */
60         movs    r6, #OCTOSPI_CCR-OCTOSPI_DR     /* load OCTOSPI_CCR address offset */
61         adds    r6, r6, r3                                      /* address of OCTOSPI_CCR */
62         wait_busy
63         ldr             r7, cr_page_read                        /* indirect read mode */
64         str             r7, [r1, #OCTOSPI_CR]           /* set mode */
65         ldmia   r2!, {r4, r5}                           /* load address offset, length */
66         subs    r2, r2, #4                                      /* point to length */
67         subs    r5, r5, #1                                      /* decrement sector length for DLR */
68         str             r5, [r1, #OCTOSPI_DLR]          /* size-1 in DLR register */
69         ldr             r7, ccr_page_read                       /* CCR for read */
70         str             r7, [r6, #OCTOSPI_CCR_CCR]      /* initiate transfer */
71         ldr             r7, tcr_page_read                       /* TCR for read */
72         str             r7, [r6, #OCTOSPI_TCR_CCR]      /* instruction */
73         ldr             r7, ir_page_read                        /* IR for read */
74         str             r7, [r6, #OCTOSPI_IR_CCR]       /* instruction */
75         str             r4, [r1, #OCTOSPI_AR]           /* store SPI start address */
76         ldr             r6, [r2, #4]                            /* load initial value */
77 read_loop:
78         ldrb    r4, [r3, #0]                            /* read next byte from DR */
79         movs    r7, #0xFF                                       /* fill bits 8-15 */
80         lsls    r7, r7, #8                                      /* with ones */
81         orrs    r4, r4, r7                                      /* copy ones to left of read byte */
82         ands    r6, r6, r4                                      /* and read byte to result */
83         lsls    r4, r4, #8                                      /* shift result into higher byte */
84         orrs    r6, r6, r4                                      /* or read byte to result */
85         subs    r5, r5, #1                                      /* decrement byte (count-1) */
86         bpl             read_loop                                       /* again if sector not completed */
87         adds    r5, r5, #1                                      /* increment count due to the -1 */
88         stmia   r2!, {r5, r6}                           /* save final count and result for sector */
89         subs    r0, r0, #1                                      /* decrement sector count */
90         bne             sector_start                            /* next sector? */
91         octospi_abort                                           /* to idle state */
92
93 exit:
94         .align  2                                                       /* align to word, bkpt is 4 words */
95         bkpt    #0                                                      /* before code end for exit_point */
96         .align  2                                                       /* align to word */
97
98 cr_page_read:
99         .space  4                                                       /* OCTOSPI_CR value for read command */
100 ccr_page_read:
101         .space  4                                                       /* OCTOSPI_CCR value for read command */
102 tcr_page_read:
103         .space  4                                                       /* OCTOSPI_TCR value for read command */
104 ir_page_read:
105         .space  4                                                       /* OCTOSPI_IR value for read command */
106
107         .equ buffer, .
108