contrib: replace the BSD-3-Clause license tag
[fw/openocd] / contrib / loaders / flash / efm32.S
1 /***************************************************************************
2  *   Copyright (C) 2011 by Andreas Fritiofson                              *
3  *   andreas.fritiofson@gmail.com                                          *
4  *   Copyright (C) 2013 by Roman Dmitrienko                                *
5  *   me@iamroman.org                                                       *
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
21  ***************************************************************************/
22
23         .text
24         .syntax unified
25         .cpu cortex-m0
26         .thumb
27         .thumb_func
28
29         /* Params:
30          * r0 - flash base (in), status (out)
31          * r1 - count (word-32bit)
32          * r2 - workarea start
33          * r3 - workarea end
34          * r4 - target address
35          * Clobbered:
36          * r5 - rp
37          * r6 - wp, tmp
38          * r7 - tmp
39          */
40
41 /* offsets of registers from flash reg base */
42 #define EFM32_MSC_WRITECTRL_OFFSET      0x008
43 #define EFM32_MSC_WRITECMD_OFFSET       0x00c
44 #define EFM32_MSC_ADDRB_OFFSET          0x010
45 #define EFM32_MSC_WDATA_OFFSET          0x018
46 #define EFM32_MSC_STATUS_OFFSET         0x01c
47
48         /* set WREN to 1 */
49         movs    r6, #1
50         str     r6, [r0, #EFM32_MSC_WRITECTRL_OFFSET]
51
52 wait_fifo:
53         ldr     r6, [r2, #0]    /* read wp */
54         cmp     r6, #0          /* abort if wp == 0 */
55         beq     exit
56         ldr     r5, [r2, #4]    /* read rp */
57         cmp     r5, r6          /* wait until rp != wp */
58         beq     wait_fifo
59
60         /* store address in MSC_ADDRB */
61         str     r4, [r0, #EFM32_MSC_ADDRB_OFFSET]
62         /* set LADDRIM bit */
63         movs    r6, #1
64         str     r6, [r0, #EFM32_MSC_WRITECMD_OFFSET]
65         /* check status for INVADDR and/or LOCKED */
66         ldr     r6, [r0, #EFM32_MSC_STATUS_OFFSET]
67         movs    r7, #6
68         tst     r6, r7
69         bne     error
70
71         /* wait for WDATAREADY */
72 wait_wdataready:
73         ldr     r6, [r0, #EFM32_MSC_STATUS_OFFSET]
74         movs    r7, #8
75         tst     r6, r7
76         beq     wait_wdataready
77
78         /* load data to WDATA */
79         ldr     r6, [r5]
80         str     r6, [r0, #EFM32_MSC_WDATA_OFFSET]
81         /* set WRITEONCE bit */
82         movs    r6, #8
83         str     r6, [r0, #EFM32_MSC_WRITECMD_OFFSET]
84
85         adds    r5, #4          /* rp++ */
86         adds    r4, #4          /* target_address++ */
87
88         /* wait until BUSY flag is reset */
89 busy:
90         ldr     r6, [r0, #EFM32_MSC_STATUS_OFFSET]
91         movs    r7, #1
92         tst     r6, r7
93         bne     busy
94
95         cmp     r5, r3          /* wrap rp at end of buffer */
96         bcc     no_wrap
97         mov     r5, r2
98         adds    r5, #8
99 no_wrap:
100         str     r5, [r2, #4]    /* store rp */
101         subs    r1, r1, #1      /* decrement word count */
102         cmp     r1, #0
103         beq     exit            /* loop if not done */
104         b       wait_fifo
105 error:
106         movs    r0, #0
107         str     r0, [r2, #4]    /* set rp = 0 on error */
108 exit:
109         mov     r0, r6          /* return status in r0 */
110         bkpt    #0