f6bf87633f5c6bf0d970ac3d9eb2bd4efb98188b
[fw/openocd] / contrib / loaders / flash / stmqspi / stmqspi_read.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), remaining bytes (out, 0 means successful)
16  * r1 - flash page size
17  * r2 - address offset into flash
18  * r3 - QSPI io_base
19  * r8 - fifo start
20  * r9 - fifo end + 1
21
22  * Clobbered:
23  * r4 - wp
24  * r5 - address of QSPI_DR
25  * r7 - tmp
26  */
27
28 #include "../../../../src/flash/nor/stmqspi.h"
29
30         .macro  qspi_abort
31         movs    r5, #(1<<SPI_ABORT)                     /* abort bit mask */
32         ldr             r7, [r3, #QSPI_CR]                      /* get QSPI_CR register */
33         orrs    r7, r7, r5                                      /* set abort bit */
34         str             r7, [r3, #QSPI_CR]                      /* store new CR register */
35         .endm
36
37         .macro  wait_busy
38 0:
39         ldr             r7, [r3, #QSPI_SR]                      /* load status */
40         lsrs    r7, r7, #(SPI_BUSY+1)           /* shift BUSY into C */
41         bcs             0b                                                      /* loop until BUSY cleared */
42         movs    r7, #(1<<SPI_TCF)                       /* TCF bitmask */
43         str             r7, [r3, #QSPI_FCR]                     /* clear TCF flag */
44         .endm
45
46 start:
47         subs    r0, r0, #1                                      /* decrement count for DLR */
48         subs    r1, r1, #1                                      /* page size mask and for DLR */
49         ldr             r4, wp                                          /* load wp */
50 start_read:
51         qspi_abort                                                      /* start in clean state */
52         movs    r5, #QSPI_DR                            /* load QSPI_DR address offset */
53         adds    r5, r5, r3                                      /* address of QSPI_DR */
54         wait_busy
55         mov             r7, r2                                          /* get current start address */
56         orrs    r7, r7, r1                                      /* end of current page */
57         subs    r7, r7, r2                                      /* count-1 to end of page */
58         cmp             r7, r0                                          /* if this count <= remaining */
59         bls             write_dlr                                       /* then read to end of page */
60         mov             r7, r0                                          /* else read all remaining */
61 write_dlr:
62         str             r7, [r3, #QSPI_DLR]                     /* size-1 in DLR register */
63         ldr             r7, ccr_page_read                       /* CCR for page read */
64         str             r7, [r3, #QSPI_CCR]                     /* initiate transfer */
65         str             r2, [r3, #QSPI_AR]                      /* store SPI start address */
66         ldr             r7, [r3, #QSPI_SR]                      /* wait for command startup */
67 read_loop:
68         ldrb    r7, [r5]                                        /* read next byte from DR */
69         strb    r7, [r4, #0]                            /* write next byte */
70         adds    r4, r4, #1                                      /* increment internal wp */
71         cmp             r4, r9                                          /* internal wp beyond end? */
72         blo             wait_fifo                                       /* if no, then ok */
73         mov             r4, r8                                          /* else wrap around */
74 wait_fifo:
75         ldr             r7, rp                                          /* get rp */
76         cmp             r7, #0                                          /* if rp equals 0 */
77         beq             exit                                            /* then abort */
78         cmp             r4, r7                                          /* check if fifo full */
79         beq             wait_fifo                                       /* wait until not full */
80         adr             r7, wp                                          /* get address of wp */
81         str             r4, [r7]                                        /* store updated wp */
82         adds    r2, r2, #1                                      /* increment address */
83         subs    r0, r0, #1                                      /* decrement (count-1) */
84         bmi             exit                                            /* stop if no data left */
85         tst             r2, r1                                          /* page end ? */
86         bne             read_loop                                       /* if not, then next byte */
87 page_end:
88         bal             start_read                                      /* then next page */
89
90 exit:
91         adds    r0, r0, #1                                      /* increment count due to the -1 */
92         qspi_abort                                                      /* to idle state */
93
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         .space  4                                                       /* not used */
99         .space  4                                                       /* not used */
100         .space  4                                                       /* not used */
101         .space  4                                                       /* not used */
102
103         .space  4                                                       /* not used */
104         .space  4                                                       /* not used */
105         .space  4                                                       /* not used */
106         .space  4                                                       /* not used */
107
108         .space  4                                                       /* not used */
109 ccr_page_read:
110         .space  4                                                       /* QSPI_CCR value for read command */
111         .space  4                                                       /* not used */
112         .space  4                                                       /* not used */
113
114         .equ wp, .                                                      /* wp, uint32_t */
115         .equ rp, wp + 4                                         /* rp, uint32_t */
116         .equ buffer, rp + 4                                     /* buffer follows right away */