contrib: replace the GPLv2-or-later license tag
[fw/openocd] / contrib / loaders / flash / mdr32fx.S
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2011 by Andreas Fritiofson                              *
5  *   andreas.fritiofson@gmail.com                                          *
6  *                                                                         *
7  *   Copyright (C) 2013 by Paul Fertser                                    *
8  *   fercerpav@gmail.com                                                   *
9  ***************************************************************************/
10
11         .text
12         .syntax unified
13         .cpu cortex-m0
14         .thumb
15         .thumb_func
16         .global write
17
18         /* Params:
19          * r0 - flash base (in), status (out)
20          * r1 - count (32bit)
21          * r2 - workarea start
22          * r3 - workarea end
23          * r4 - target address
24          * Clobbered:
25          * r5 - rp
26          * r6 - wp, tmp
27          * r7 - current FLASH_CMD
28          */
29
30 #define FLASH_CMD       0x00
31 #define FLASH_ADR       0x04
32 #define FLASH_DI        0x08
33
34 #define FLASH_NVSTR     (1 << 13)
35 #define FLASH_PROG      (1 << 12)
36 #define FLASH_MAS1      (1 << 11)
37 #define FLASH_ERASE     (1 << 10)
38 #define FLASH_SE        (1 << 8)
39 #define FLASH_YE        (1 << 7)
40 #define FLASH_XE        (1 << 6)
41
42         ldr     r7, [r0, #FLASH_CMD]
43 wait_fifo:
44         ldr     r6, [r2, #0]    /* read wp */
45         cmp     r6, #0                  /* abort if wp == 0 */
46         beq     exit
47         ldr     r5, [r2, #4]    /* read rp */
48         cmp     r5, r6                  /* wait until rp != wp */
49         beq     wait_fifo
50
51         ldr     r6, [r5]        /* "*target_address++ = *rp++" */
52         str     r4, [r0, #FLASH_ADR]
53         str     r6, [r0, #FLASH_DI]
54
55         ldr     r6, =(FLASH_XE | FLASH_PROG)
56         orrs    r7, r7, r6
57         str     r7, [r0, #FLASH_CMD]
58         # wait 5us
59         movs    r6, #5
60         bl      delay
61         ldr     r6, =#FLASH_NVSTR
62         orrs    r7, r7, r6
63         str     r7, [r0, #FLASH_CMD]
64         # wait 10us
65         movs    r6, #13
66         bl      delay
67         movs    r6, #FLASH_YE
68         orrs    r7, r7, r6
69         str     r7, [r0, #FLASH_CMD]
70         # wait 40us
71         movs    r6, #61
72         bl      delay
73         movs    r6, #FLASH_YE
74         bics    r7, r7, r6
75         str     r7, [r0, #FLASH_CMD]
76         ldr     r6, =#FLASH_PROG
77         bics    r7, r7, r6
78         str     r7, [r0, #FLASH_CMD]
79         # wait 5us
80         movs    r6, #5
81         bl      delay
82         ldr     r6, =#(FLASH_XE | FLASH_NVSTR)
83         bics    r7, r7, r6
84         str     r7, [r0, #FLASH_CMD]
85
86         adds    r5, #4
87         adds    r4, #4
88
89         cmp     r5, r3                  /* wrap rp at end of buffer */
90         bcc     no_wrap
91         mov     r5, r2
92         adds    r5, #8
93 no_wrap:
94         str     r5, [r2, #4]    /* store rp */
95         subs    r1, r1, #1              /* decrement word count */
96         cmp     r1, #0
97         beq     exit            /* loop if not done */
98         b       wait_fifo
99 exit:
100         mov             r0, r6                  /* return status in r0 */
101         bkpt    #0
102
103         /* r6 - in
104          * for r6 == 1 it'll take:
105          *  1 (prepare operand) + 4 (bl) + 2 (subs+cmp) + 1 (bne) + 3 (b) ->
106          *  11 tacts == 1.4us with 8MHz
107          * every extra iteration will take 5 tacts == 0.6us */
108 delay:
109         subs    r6, r6, #1
110         cmp     r6, #0
111         bne     delay
112         bx      lr