1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * Copyright (C) 2011 by Andreas Fritiofson *
5 * andreas.fritiofson@gmail.com *
6 * Copyright (C) 2013 by Roman Dmitrienko *
8 ***************************************************************************/
17 * r0 - flash base (in), status (out)
18 * r1 - count (word-32bit)
28 /* offsets of registers from flash reg base */
29 #define EFM32_MSC_WRITECTRL_OFFSET 0x008
30 #define EFM32_MSC_WRITECMD_OFFSET 0x00c
31 #define EFM32_MSC_ADDRB_OFFSET 0x010
32 #define EFM32_MSC_WDATA_OFFSET 0x018
33 #define EFM32_MSC_STATUS_OFFSET 0x01c
37 str r6, [r0, #EFM32_MSC_WRITECTRL_OFFSET]
40 ldr r6, [r2, #0] /* read wp */
41 cmp r6, #0 /* abort if wp == 0 */
43 ldr r5, [r2, #4] /* read rp */
44 cmp r5, r6 /* wait until rp != wp */
47 /* store address in MSC_ADDRB */
48 str r4, [r0, #EFM32_MSC_ADDRB_OFFSET]
51 str r6, [r0, #EFM32_MSC_WRITECMD_OFFSET]
52 /* check status for INVADDR and/or LOCKED */
53 ldr r6, [r0, #EFM32_MSC_STATUS_OFFSET]
58 /* wait for WDATAREADY */
60 ldr r6, [r0, #EFM32_MSC_STATUS_OFFSET]
65 /* load data to WDATA */
67 str r6, [r0, #EFM32_MSC_WDATA_OFFSET]
68 /* set WRITEONCE bit */
70 str r6, [r0, #EFM32_MSC_WRITECMD_OFFSET]
72 adds r5, #4 /* rp++ */
73 adds r4, #4 /* target_address++ */
75 /* wait until BUSY flag is reset */
77 ldr r6, [r0, #EFM32_MSC_STATUS_OFFSET]
82 cmp r5, r3 /* wrap rp at end of buffer */
87 str r5, [r2, #4] /* store rp */
88 subs r1, r1, #1 /* decrement word count */
90 beq exit /* loop if not done */
94 str r0, [r2, #4] /* set rp = 0 on error */
96 mov r0, r6 /* return status in r0 */