5865da007b1ca57ba9ef89b53ad88529de3e2454
[openocd.git] / contrib / loaders / flash / mrvlqspi_write.S
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4 * Copyright (C) 2014 by Mahavir Jain <mjain@marvell.com> *
5 * *
6 * Adapted from (contrib/loaders/flash/lpcspifi_write.S): *
7 * Copyright (C) 2012 by George Harris *
8 * george@luminairecoffee.com *
9 ***************************************************************************/
10
11 .text
12 .syntax unified
13 .cpu cortex-m3
14 .thumb
15 .thumb_func
16
17 /*
18 * For compilation:
19 * arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -c contrib/loaders/flash/mrvlqspi_write.S
20 * arm-none-eabi-objcopy -O binary mrvlqspi_write.o code.bin
21 * Copy code.bin into mrvlqspi flash driver
22 */
23
24 /*
25 * Params :
26 * r0 = workarea start, status (out)
27 * r1 = workarea end
28 * r2 = target address (offset from flash base)
29 * r3 = count (bytes)
30 * r4 = page size
31 * r5 = qspi base address
32 * Clobbered:
33 * r7 - rp
34 * r8 - wp, tmp
35 * r9 - send/receive data
36 * r10 - current page end address
37 */
38
39 #define CNTL 0x0
40 #define CONF 0x4
41 #define DOUT 0x8
42 #define DIN 0xc
43 #define INSTR 0x10
44 #define ADDR 0x14
45 #define RDMODE 0x18
46 #define HDRCNT 0x1c
47 #define DINCNT 0x20
48
49 #define SS_EN (1 << 0)
50 #define XFER_RDY (1 << 1)
51 #define RFIFO_EMPTY (1 << 4)
52 #define WFIFO_EMPTY (1 << 6)
53 #define WFIFO_FULL (1 << 7)
54 #define FIFO_FLUSH (1 << 9)
55 #define RW_EN (1 << 13)
56 #define XFER_STOP (1 << 14)
57 #define XFER_START (1 << 15)
58
59 #define INS_WRITE_ENABLE 0x06
60 #define INS_READ_STATUS 0x05
61 #define INS_PAGE_PROGRAM 0x02
62
63 init:
64 mov.w r10, #0x00
65 find_next_page_boundary:
66 add r10, r4 /* Increment to the next page */
67 cmp r10, r2
68 /* If we have not reached the next page boundary after the target address, keep going */
69 bls find_next_page_boundary
70 write_enable:
71 /* Flush read/write fifos */
72 bl flush_fifo
73
74 /* Instruction byte 1 */
75 movs r8, #0x1
76 str r8, [r5, #HDRCNT]
77
78 /* Set write enable instruction */
79 movs r8, #INS_WRITE_ENABLE
80 str r8, [r5, #INSTR]
81
82 movs r9, #0x1
83 bl start_tx
84 bl stop_tx
85 page_program:
86 /* Instruction byte 1, Addr byte 3 */
87 movs r8, #0x31
88 str r8, [r5, #HDRCNT]
89 /* Todo: set addr and data pin to single */
90 write_address:
91 mov r8, r2
92 str r8, [r5, #ADDR]
93 /* Set page program instruction */
94 movs r8, #INS_PAGE_PROGRAM
95 str r8, [r5, #INSTR]
96 /* Start write transfer */
97 movs r9, #0x1
98 bl start_tx
99 wait_fifo:
100 ldr r8, [r0] /* read the write pointer */
101 cmp r8, #0 /* if it's zero, we're gonzo */
102 beq exit
103 ldr r7, [r0, #4] /* read the read pointer */
104 cmp r7, r8 /* wait until they are not equal */
105 beq wait_fifo
106 write:
107 ldrb r9, [r7], #0x01 /* Load one byte from the FIFO, increment the read pointer by 1 */
108 bl write_data /* send the byte to the flash chip */
109
110 cmp r7, r1 /* wrap the read pointer if it is at the end */
111 it cs
112 addcs r7, r0, #8 /* skip loader args */
113 str r7, [r0, #4] /* store the new read pointer */
114 subs r3, r3, #1 /* decrement count */
115 cmp r3, #0 /* Exit if we have written everything */
116 beq write_wait
117 add r2, #1 /* Increment flash address by 1 */
118 cmp r10, r2 /* See if we have reached the end of a page */
119 bne wait_fifo /* If not, keep writing bytes */
120 write_wait:
121 bl stop_tx /* Otherwise, end the command and keep going w/ the next page */
122 add r10, r4 /* Move up the end-of-page address by the page size*/
123 check_flash_busy: /* Wait for the flash to finish the previous page write */
124 /* Flush read/write fifos */
125 bl flush_fifo
126 /* Instruction byte 1 */
127 movs r8, #0x1
128 str r8, [r5, #HDRCNT]
129 /* Continuous data in of status register */
130 movs r8, #0x0
131 str r8, [r5, #DINCNT]
132 /* Set write enable instruction */
133 movs r8, #INS_READ_STATUS
134 str r8, [r5, #INSTR]
135 /* Start read transfer */
136 movs r9, #0x0
137 bl start_tx
138 wait_flash_busy:
139 bl read_data
140 and.w r9, r9, #0x1
141 cmp r9, #0x0
142 bne.n wait_flash_busy
143 bl stop_tx
144 cmp r3, #0
145 bne.n write_enable /* If it is done, start a new page write */
146 b exit /* All data written, exit */
147
148 write_data: /* Send/receive 1 byte of data over QSPI */
149 ldr r8, [r5, #CNTL]
150 lsls r8, r8, #24
151 bmi.n write_data
152 str r9, [r5, #DOUT]
153 bx lr
154
155 read_data: /* Read 1 byte of data over QSPI */
156 ldr r8, [r5, #CNTL]
157 lsls r8, r8, #27
158 bmi.n read_data
159 ldr r9, [r5, #DIN]
160 bx lr
161
162 flush_fifo: /* Flush read write fifos */
163 ldr r8, [r5, #CONF]
164 orr.w r8, r8, #FIFO_FLUSH
165 str r8, [r5, #CONF]
166 flush_reset:
167 ldr r8, [r5, #CONF]
168 lsls r8, r8, #22
169 bmi.n flush_reset
170 bx lr
171
172 start_tx:
173 ldr r8, [r5, #CNTL]
174 orr.w r8, r8, #SS_EN
175 str r8, [r5, #CNTL]
176 xfer_rdy:
177 ldr r8, [r5, #CNTL]
178 lsls r8, r8, #30
179 bpl.n xfer_rdy
180 ldr r8, [r5, #CONF]
181 bfi r8, r9, #13, #1
182 orr.w r8, r8, #XFER_START
183 str r8, [r5, #CONF]
184 bx lr
185
186 stop_tx:
187 ldr r8, [r5, #CNTL]
188 lsls r8, r8, #30
189 bpl.n stop_tx
190 wfifo_wait:
191 ldr r8, [r5, #CNTL]
192 lsls r8, r8, #25
193 bpl.n wfifo_wait
194 ldr r8, [r5, #CONF]
195 orr.w r8, r8, #XFER_STOP
196 str r8, [r5, #CONF]
197 xfer_start:
198 ldr r8, [r5, #CONF]
199 lsls r8, r8, #16
200 bmi.n xfer_start
201 ss_disable:
202 # Disable SS_EN
203 ldr r8, [r5, #CNTL]
204 bic.w r8, r8, #SS_EN
205 str r8, [r5, #CNTL]
206 wait:
207 ldr r8, [r5, #CNTL]
208 lsls r8, r8, #30
209 bpl.n wait
210 bx lr
211
212 error:
213 movs r0, #0
214 str r0, [r2, #4] /* set rp = 0 on error */
215 exit:
216 mov r0, r6
217 bkpt #0x00
218
219 .end

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)