contrib: replace the GPLv2-or-later license tag
[openocd.git] / contrib / loaders / flash / stmqspi / stmoctospi_read.S
blob8cc786ed6f3bb6b4b2f24af9e82ed82b8b687749
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4  *   Copyright (C) 2019 by Andreas Bolsch                                  *
5  *   andreas.bolsch@mni.thm.de                                             *
6  ***************************************************************************/
8         .text
9         .syntax unified
10         .cpu cortex-m0
11         .thumb
12         .thumb_func
14 /* Params:
15  * r0 - total count (bytes), remaining bytes (out, 0 means successful)
16  * r1 - flash page size
17  * r2 - address offset into flash
18  * r3 - OCTOSPI io_base
19  * r8 - fifo start
20  * r9 - fifo end + 1
22  * Clobbered:
23  * r4 - wp
24  * r5 - address of OCTOSPI_DR
25  * r6 - address of OCTOSPI_CCR
26  * r7 - tmp
27  */
29 #include "../../../../src/flash/nor/stmqspi.h"
31 #define OCTOSPI_CCR_CCR                                 (OCTOSPI_CCR - OCTOSPI_CCR)
32 #define OCTOSPI_TCR_CCR                                 (OCTOSPI_TCR - OCTOSPI_CCR)
33 #define OCTOSPI_IR_CCR                                  (OCTOSPI_IR - OCTOSPI_CCR)
35         .macro  octospi_abort
36         movs    r5, #(1<<SPI_ABORT)                     /* abort bit mask */
37         ldr             r7, [r3, #OCTOSPI_CR]           /* get OCTOSPI CR register */
38         orrs    r7, r7, r5                                      /* set abort bit */
39         str             r7, [r3, #OCTOSPI_CR]           /* store new CR register */
40         .endm
42         .macro  wait_busy
44         ldr             r7, [r3, #OCTOSPI_SR]           /* load status */
45         lsrs    r7, r7, #(SPI_BUSY+1)           /* shift BUSY into C */
46         bcs             0b                                                      /* loop until BUSY cleared */
47         movs    r7, #(1<<SPI_TCF)                       /* TCF bitmask */
48         str             r7, [r3, #OCTOSPI_FCR]          /* clear TCF flag */
49         .endm
51 start:
52         subs    r0, r0, #1                                      /* decrement count for DLR */
53         subs    r1, r1, #1                                      /* page size mask and for DLR */
54         ldr             r4, wp                                          /* load wp */
55 start_read:
56         octospi_abort                                           /* start in clean state */
57         movs    r5, #OCTOSPI_DR                         /* load OCTOSPI_DR address offset */
58         adds    r5, r5, r3                                      /* address of OCTOSPI_DR */
59         movs    r6, #OCTOSPI_CCR-OCTOSPI_DR     /* load OCTOSPI_CCR address offset */
60         adds    r6, r6, r5                                      /* address of OCTOSPI_CCR */
61         wait_busy
62         ldr             r7, cr_page_read                        /* indirect read mode */
63         str             r7, [r3, #OCTOSPI_CR]           /* set mode */
64         mov             r7, r2                                          /* get current start address */
65         orrs    r7, r7, r1                                      /* end of current page */
66         subs    r7, r7, r2                                      /* count-1 to end of page */
67         cmp             r7, r0                                          /* if this count <= remaining */
68         bls             write_dlr                                       /* then write to end of page */
69         mov             r7, r0                                          /* else write all remaining */
70 write_dlr:
71         str             r7, [r3, #OCTOSPI_DLR]          /* size-1 in DLR register */
72         ldr             r7, ccr_page_read                       /* CCR for read */
73         str             r7, [r6, #OCTOSPI_CCR_CCR]      /* initiate transfer */
74         ldr             r7, tcr_page_read                       /* TCR for read */
75         str             r7, [r6, #OCTOSPI_TCR_CCR]      /* instruction */
76         ldr             r7, ir_page_read                        /* IR for read */
77         str             r7, [r6, #OCTOSPI_IR_CCR]       /* instruction */
78         str             r2, [r3, #OCTOSPI_AR]           /* store SPI start address */
79 read_loop:
80         ldrb    r7, [r5]                                        /* read next byte from DR */
81         strb    r7, [r4, #0]                            /* write next byte */
82         adds    r4, r4, #1                                      /* increment internal wp */
83         cmp             r4, r9                                          /* internal wp beyond end? */
84         blo             wait_fifo                                       /* if no, then ok */
85         mov             r4, r8                                          /* else wrap around */
86 wait_fifo:
87         ldr             r7, rp                                          /* get rp */
88         cmp             r7, #0                                          /* if rp equals 0 */
89         beq             exit                                            /* then abort */
90         cmp             r4, r7                                          /* check if fifo full */
91         beq             wait_fifo                                       /* wait until not full */
92         adr             r7, wp                                          /* get address of wp */
93         str             r4, [r7]                                        /* store updated wp */
94         adds    r2, r2, #1                                      /* increment address */
95         subs    r0, r0, #1                                      /* decrement (count-1) */
96         bmi             exit                                            /* stop if no data left */
97         tst             r2, r1                                          /* page end ? */
98         bne             read_loop                                       /* if not, then next byte */
99 page_end:
100         bal             start_read                                      /* then next page */
102 exit:
103         adds    r0, r0, #1                                      /* increment count due to the -1 */
104         octospi_abort                                           /* to idle state */
106         .align  2                                                       /* align to word, bkpt is 4 words */
107         bkpt    #0                                                      /* before code end for exit_point */
108         .align  2                                                       /* align to word */
110         .space  4                                                       /* not used */
111         .space  4                                                       /* not used */
112         .space  4                                                       /* not used */
113         .space  4                                                       /* not used */
115         .space  4                                                       /* not used */
116         .space  4                                                       /* not used */
117         .space  4                                                       /* not used */
118         .space  4                                                       /* not used */
120 cr_page_read:
121         .space  4                                                       /* OCTOSPI_CR value for read command */
122 ccr_page_read:
123         .space  4                                                       /* OCTOSPI_CCR value for read command */
124 tcr_page_read:
125         .space  4                                                       /* OCTOSPI_TCR value for read command */
126 ir_page_read:
127         .space  4                                                       /* OCTOSPI_IR value for read command */
129         .equ wp, .                                                      /* wp, uint32_t */
130         .equ rp, wp + 4                                         /* rp, uint32_t */
131         .equ buffer, rp + 4                                     /* buffer follows right away */