contrib: replace the GPLv2-or-later license tag
[fw/openocd] / contrib / loaders / flash / stmqspi / stmqspi_crc32.S
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2019 by Andreas Bolsch                                  *
5  *   andreas.bolsch@mni.thm.de                                             *
6  ***************************************************************************/
7
8         .text
9         .syntax unified
10         .cpu cortex-m0
11         .thumb
12         .thumb_func
13
14 /* Params:
15  * r0 - total count (bytes), crc32 (out)
16  * r1 - flash page size
17  * r2 - address offset into flash
18  * r3 - QSPI io_base
19
20  * Clobbered:
21  * r4 - rp
22  * r5 - address of QSPI_DR
23  * r7 - tmp
24  */
25
26 #include "../../../../src/flash/nor/stmqspi.h"
27
28         .macro  qspi_abort
29         movs    r5, #(1<<SPI_ABORT)                     /* abort bit mask */
30         ldr             r7, [r3, #QSPI_CR]                      /* get QSPI_CR register */
31         orrs    r7, r7, r5                                      /* set abort bit */
32         str             r7, [r3, #QSPI_CR]                      /* store new CR register */
33         .endm
34
35         .macro  wait_busy
36 0:
37         ldr             r7, [r3, #QSPI_SR]                      /* load status */
38         lsrs    r7, r7, #(SPI_BUSY+1)           /* shift BUSY into C */
39         bcs             0b                                                      /* loop until BUSY cleared */
40         movs    r7, #(1<<SPI_TCF)                       /* TCF bitmask */
41         str             r7, [r3, #QSPI_FCR]                     /* clear TCF flag */
42         .endm
43
44 start:
45         subs    r0, r0, #1                                      /* decrement count for DLR */
46         subs    r1, r1, #1                                      /* page size mask and for DLR */
47         movs    r4, #0x00                                       /* initialize crc */
48         mvns    r4, r4                                          /* to 0xFFFFFFFF */
49 start_read:
50         qspi_abort                                                      /* start in clean state */
51         movs    r5, #QSPI_DR                            /* load QSPI_DR address offset */
52         adds    r5, r5, r3                                      /* address of QSPI_DR */
53         wait_busy
54         mov             r7, r2                                          /* get current start address */
55         orrs    r7, r7, r1                                      /* end of current page */
56         subs    r7, r7, r2                                      /* count-1 to end of page */
57         cmp             r7, r0                                          /* if this count <= remaining */
58         bls             write_dlr                                       /* then read to end of page */
59         mov             r7, r0                                          /* else read all remaining */
60 write_dlr:
61         str             r7, [r3, #QSPI_DLR]                     /* size-1 in DLR register */
62         ldr             r7, ccr_page_read                       /* CCR for page read */
63         str             r7, [r3, #QSPI_CCR]                     /* initiate transfer */
64         str             r2, [r3, #QSPI_AR]                      /* store SPI start address */
65         ldr             r7, [r3, #QSPI_SR]                      /* wait for command startup */
66         ldr             r6, =0x04C11DB7                         /* CRC32 polynomial */
67 read_loop:
68         ldrb    r7, [r5]                                        /* read next byte from DR */
69         lsls    r7, r7, #24                                     /* shift into msb */
70         eors    r4, r4, r7
71         .rept   8                                                       /* unrolled bit loop */
72         asrs    r7, r4, #31                                     /* copy bit 31 into bits 0 to 31 */
73         ands    r7, r7, r6                                      /* r7 neg. -> CRC32XOR, pos. -> 0x0 */
74         lsls    r4, r4, #1                                      /* shift result */
75         eors    r4, r4, r7                                      /* eor by CRC32XOR or 0x0 */
76         .endr
77         adds    r2, r2, #1                                      /* increment address */
78         subs    r0, r0, #1                                      /* decrement (count-1) */
79         bmi             exit                                            /* stop if no data left */
80         tst             r2, r1                                          /* page end ? */
81         bne             read_loop                                       /* if not, then next byte */
82 page_end:
83         bal             start_read                                      /* then next page */
84         .pool
85
86 exit:
87         mvns    r0, r4                                          /* invert to get final result */
88         qspi_abort                                                      /* to idle state */
89         .align  2                                                       /* align to word, bkpt is 4 words */
90         bkpt    #0                                                      /* before code end for exit_point */
91         .align  2                                                       /* align to word */
92
93         .space  4                                                       /* not used */
94 ccr_page_read:
95         .space  4                                                       /* QSPI_CCR value for read command */
96         .space  4                                                       /* not used */
97         .space  4                                                       /* not used */