contrib: replace the GPLv2-or-later license tag
[fw/openocd] / contrib / loaders / flash / stmqspi / stmoctospi_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 - OCTOSPI io_base
19
20  * Clobbered:
21  * r4 - tmp
22  * r5 - address of OCTOSPI_DR
23  * r6 - address of OCTOSPI_CCR
24  * r7 - tmp
25  */
26
27 #include "../../../../src/flash/nor/stmqspi.h"
28
29 #define OCTOSPI_CCR_CCR                                 (OCTOSPI_CCR - OCTOSPI_CCR)
30 #define OCTOSPI_TCR_CCR                                 (OCTOSPI_TCR - OCTOSPI_CCR)
31 #define OCTOSPI_IR_CCR                                  (OCTOSPI_IR - OCTOSPI_CCR)
32
33         .macro  octospi_abort
34         movs    r5, #(1<<SPI_ABORT)                     /* abort bit mask */
35         ldr             r7, [r3, #OCTOSPI_CR]           /* get OCTOSPI CR register */
36         orrs    r7, r7, r5                                      /* set abort bit */
37         str             r7, [r3, #OCTOSPI_CR]           /* store new CR register */
38         .endm
39
40         .macro  wait_busy
41 0:
42         ldr             r7, [r3, #OCTOSPI_SR]           /* load status */
43         lsrs    r7, r7, #(SPI_BUSY+1)           /* shift BUSY into C */
44         bcs             0b                                                      /* loop until BUSY cleared */
45         movs    r7, #(1<<SPI_TCF)                       /* TCF bitmask */
46         str             r7, [r3, #OCTOSPI_FCR]          /* clear TCF flag */
47         .endm
48
49 start:
50         subs    r0, r0, #1                                      /* decrement count for DLR */
51         subs    r1, r1, #1                                      /* page size mask and for DLR */
52         movs    r4, #0x00                                       /* initialize crc */
53         mvns    r4, r4                                          /* to 0xFFFFFFFF */
54 start_read:
55         octospi_abort                                           /* start in clean state */
56         movs    r5, #OCTOSPI_DR                         /* load OCTOSPI_DR address offset */
57         adds    r5, r5, r3                                      /* address of OCTOSPI_DR */
58         movs    r6, #OCTOSPI_CCR-OCTOSPI_DR     /* load OCTOSPI_CCR address offset */
59         adds    r6, r6, r5                                      /* address of OCTOSPI_CCR */
60         wait_busy
61         ldr             r7, cr_page_read                        /* indirect read mode */
62         str             r7, [r3, #OCTOSPI_CR]           /* set mode */
63         mov             r7, r2                                          /* get current start address */
64         orrs    r7, r7, r1                                      /* end of current page */
65         subs    r7, r7, r2                                      /* count-1 to end of page */
66         cmp             r7, r0                                          /* if this count <= remaining */
67         bls             write_dlr                                       /* then read to end of page */
68         mov             r7, r0                                          /* else read all remaining */
69 write_dlr:
70         str             r7, [r3, #OCTOSPI_DLR]          /* size-1 in DLR register */
71         ldr             r7, ccr_page_read                       /* CCR for read */
72         str             r7, [r6, #OCTOSPI_CCR_CCR]      /* initiate transfer */
73         ldr             r7, tcr_page_read                       /* TCR for read */
74         str             r7, [r6, #OCTOSPI_TCR_CCR]      /* instruction */
75         ldr             r7, ir_page_read                        /* IR for read */
76         str             r7, [r6, #OCTOSPI_IR_CCR]       /* instruction */
77         str             r2, [r3, #OCTOSPI_AR]           /* store SPI start address */
78         ldr             r6, =0x04C11DB7                         /* CRC32 polynomial */
79 read_loop:
80         ldrb    r7, [r5]                                        /* read next byte from DR */
81         lsls    r7, r7, #24                                     /* shift into msb */
82         eors    r4, r4, r7
83         .rept   8                                                       /* unrolled bit loop */
84         asrs    r7, r4, #31                                     /* copy bit 31 into bits 0 to 31 */
85         ands    r7, r7, r6                                      /* r7 neg. -> CRC32XOR, pos. -> 0x0 */
86         lsls    r4, r4, #1                                      /* shift result */
87         eors    r4, r4, r7                                      /* eor by CRC32XOR or 0x0 */
88         .endr
89         adds    r2, r2, #1                                      /* increment address */
90         subs    r0, r0, #1                                      /* decrement (count-1) */
91         bmi             exit                                            /* stop if no data left */
92         tst             r2, r1                                          /* page end ? */
93         bne             read_loop                                       /* if not, then next byte */
94 page_end:
95         bal             start_read                                      /* then next page */
96         .pool
97
98 exit:
99         mvns    r0, r4                                          /* invert to get final result */
100         octospi_abort                                           /* to idle state */
101         .align  2                                                       /* align to word, bkpt is 4 words */
102         bkpt    #0                                                      /* before code end for exit_point */
103         .align  2                                                       /* align to word */
104
105 cr_page_read:
106         .space  4                                                       /* OCTOSPI_CR value for read command */
107 ccr_page_read:
108         .space  4                                                       /* OCTOSPI_CCR value for read command */
109 tcr_page_read:
110         .space  4                                                       /* OCTOSPI_TCR value for read command */
111 ir_page_read:
112         .space  4                                                       /* OCTOSPI_IR value for read command */