jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / contrib / loaders / flash / sh_qspi / sh_qspi.S
1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3 * SH QSPI (Quad SPI) driver
4 * Copyright (C) 2019 Marek Vasut <marek.vasut@gmail.com>
5 */
6
7 #define BIT(n) (1UL << (n))
8 /* SH QSPI register bit masks <REG>_<BIT> */
9 #define SPCR_MSTR 0x08
10 #define SPCR_SPE 0x40
11 #define SPSR_SPRFF 0x80
12 #define SPSR_SPTEF 0x20
13 #define SPPCR_IO3FV 0x04
14 #define SPPCR_IO2FV 0x02
15 #define SPPCR_IO1FV 0x01
16 #define SPBDCR_RXBC0 BIT(0)
17 #define SPCMD_SCKDEN BIT(15)
18 #define SPCMD_SLNDEN BIT(14)
19 #define SPCMD_SPNDEN BIT(13)
20 #define SPCMD_SSLKP BIT(7)
21 #define SPCMD_BRDV0 BIT(2)
22 #define SPCMD_INIT1 SPCMD_SCKDEN | SPCMD_SLNDEN | \
23 SPCMD_SPNDEN | SPCMD_SSLKP | \
24 SPCMD_BRDV0
25 #define SPCMD_INIT2 SPCMD_SPNDEN | SPCMD_SSLKP | \
26 SPCMD_BRDV0
27 #define SPBFCR_TXRST BIT(7)
28 #define SPBFCR_RXRST BIT(6)
29 #define SPBFCR_TXTRG 0x30
30 #define SPBFCR_RXTRG 0x07
31
32 /* SH QSPI register set */
33 #define SH_QSPI_SPCR 0x00
34 #define SH_QSPI_SSLP 0x01
35 #define SH_QSPI_SPPCR 0x02
36 #define SH_QSPI_SPSR 0x03
37 #define SH_QSPI_SPDR 0x04
38 #define SH_QSPI_SPSCR 0x08
39 #define SH_QSPI_SPSSR 0x09
40 #define SH_QSPI_SPBR 0x0a
41 #define SH_QSPI_SPDCR 0x0b
42 #define SH_QSPI_SPCKD 0x0c
43 #define SH_QSPI_SSLND 0x0d
44 #define SH_QSPI_SPND 0x0e
45 #define SH_QSPI_DUMMY0 0x0f
46 #define SH_QSPI_SPCMD0 0x10
47 #define SH_QSPI_SPCMD1 0x12
48 #define SH_QSPI_SPCMD2 0x14
49 #define SH_QSPI_SPCMD3 0x16
50 #define SH_QSPI_SPBFCR 0x18
51 #define SH_QSPI_DUMMY1 0x19
52 #define SH_QSPI_SPBDCR 0x1a
53 #define SH_QSPI_SPBMUL0 0x1c
54 #define SH_QSPI_SPBMUL1 0x20
55 #define SH_QSPI_SPBMUL2 0x24
56 #define SH_QSPI_SPBMUL3 0x28
57
58 .syntax unified
59 .arm
60 .text
61
62 .macro wait_for_spsr, spsrbit
63 1: ldrb r12, [r0, #SH_QSPI_SPSR]
64 tst r12, \spsrbit
65 beq 1b
66 .endm
67
68 .macro sh_qspi_xfer
69 bl sh_qspi_cs_activate
70 str r6, [r0, SH_QSPI_SPBMUL0]
71 bl sh_qspi_xfer_common
72 bl sh_qspi_cs_deactivate
73 .endm
74
75 .macro sh_qspi_write_enable
76 ldr r4, =SPIFLASH_WRITE_ENABLE
77 adr r5, _start
78 add r4, r5
79 mov r5, #0x0
80 mov r6, #0x1
81 sh_qspi_xfer
82 .endm
83
84 .macro sh_qspi_wait_till_ready
85 1: ldr r4, =SPIFLASH_READ_STATUS
86 adr r5, _start
87 add r4, r5
88 mov r5, #0x0
89 mov r6, #0x2
90 sh_qspi_xfer
91 and r13, #0x1
92 cmp r13, #0x1
93 beq 1b
94 .endm
95
96 /*
97 * r0: controller base address
98 * r1: data buffer base address
99 * r2: BIT(31) -- page program (not read)
100 * BIT(30) -- 4-byte address (not 3-byte)
101 * BIT(29) -- 512-byte page (not 256-byte)
102 * BIT(27:20) -- SF command
103 * BIT(19:0) -- amount of data to read/write
104 * r3: SF target address
105 *
106 * r7: data size
107 * r8: page size
108 *
109 * r14: lr, link register
110 * r15: pc, program counter
111 *
112 * Clobber: r4, r5, r6, r7, r8
113 */
114
115 .global _start
116 _start:
117 bic r7, r2, #0xff000000
118 bic r7, r7, #0x00f00000
119
120 and r8, r2, #(1 << 31)
121 cmp r8, #(1 << 31)
122 beq do_page_program
123
124 /* fast read */
125
126 bl sh_qspi_cs_activate
127
128 bl sh_qspi_setup_command
129 add r8, r6, r7
130 str r8, [r0, SH_QSPI_SPBMUL0]
131 bl sh_qspi_xfer_common
132
133 mov r4, #0x0
134 mov r5, r1
135 mov r6, r7
136 bl sh_qspi_xfer_common
137
138 bl sh_qspi_cs_deactivate
139
140 b end
141
142 do_page_program:
143
144 mov r8, #0x100
145 tst r2, (1 << 29)
146 movne r8, #0x200
147
148 do_pp_next_page:
149 /* Check if less then page bytes left. */
150 cmp r7, r8
151 movlt r8, r7
152
153 sh_qspi_write_enable
154
155 bl sh_qspi_cs_activate
156
157 bl sh_qspi_setup_command
158 str r6, [r0, SH_QSPI_SPBMUL0]
159 bl sh_qspi_xfer_common
160
161 mov r4, r1
162 mov r5, #0x0
163 mov r6, r8
164
165 bl sh_qspi_xfer_common
166
167 bl sh_qspi_cs_deactivate
168
169 sh_qspi_wait_till_ready
170
171 add r1, r8
172 add r3, r8
173 sub r7, r8
174 cmp r7, #0
175
176 bne do_pp_next_page
177
178 end:
179 bkpt #0
180
181 sh_qspi_cs_activate:
182 /* Set master mode only */
183 mov r12, #SPCR_MSTR
184 strb r12, [r0, SH_QSPI_SPCR]
185
186 /* Set command */
187 mov r12, #SPCMD_INIT1
188 strh r12, [r0, SH_QSPI_SPCMD0]
189
190 /* Reset transfer and receive Buffer */
191 ldrb r12, [r0, SH_QSPI_SPSCR]
192 orr r12, #(SPBFCR_TXRST | SPBFCR_RXRST)
193 strb r12, [r0, SH_QSPI_SPBFCR]
194
195 /* Clear transfer and receive Buffer control bit */
196 ldrb r12, [r0, SH_QSPI_SPBFCR]
197 bic r12, #(SPBFCR_TXRST | SPBFCR_RXRST)
198 strb r12, [r0, SH_QSPI_SPBFCR]
199
200 /* Set sequence control method. Use sequence0 only */
201 mov r12, #0x00
202 strb r12, [r0, SH_QSPI_SPSCR]
203
204 /* Enable SPI function */
205 ldrb r12, [r0, SH_QSPI_SPCR]
206 orr r12, #SPCR_SPE
207 strb r12, [r0, SH_QSPI_SPCR]
208
209 mov pc, lr
210
211 sh_qspi_cs_deactivate:
212 /* Disable SPI function */
213 ldrb r12, [r0, SH_QSPI_SPCR]
214 bic r12, #SPCR_SPE
215 strb r12, [r0, SH_QSPI_SPCR]
216
217 mov pc, lr
218
219 /*
220 * r0, controller base address
221 * r4, tx buffer
222 * r5, rx buffer
223 * r6, xfer len, non-zero
224 *
225 * Upon exit, r13 contains the last byte in SPDR
226 *
227 * Clobber: r11, r12, r13
228 */
229 sh_qspi_xfer_common:
230 prepcopy:
231 ldr r13, [r0, #SH_QSPI_SPBFCR]
232 orr r13, #(SPBFCR_TXTRG | SPBFCR_RXTRG)
233 mov r11, #32
234 cmp r6, #32
235
236 biclt r13, #(SPBFCR_TXTRG | SPBFCR_RXTRG)
237 movlt r11, #1
238
239 copy:
240 str r13, [r0, #SH_QSPI_SPBFCR]
241
242 wait_for_spsr SPSR_SPTEF
243
244 mov r12, r11
245 mov r13, #0
246 cmp r4, #0
247 beq 3f
248
249 2: ldrb r13, [r4], #1
250 strb r13, [r0, #SH_QSPI_SPDR]
251 subs r12, #1
252 bne 2b
253 b 4f
254
255 3: strb r13, [r0, #SH_QSPI_SPDR]
256 subs r12, #1
257 bne 3b
258
259 4: wait_for_spsr SPSR_SPRFF
260
261 mov r12, r11
262 cmp r5, #0
263 beq 6f
264
265 5: ldrb r13, [r0, #SH_QSPI_SPDR]
266 strb r13, [r5], #1
267 subs r12, #1
268 bne 5b
269 b 7f
270
271 6: ldrb r13, [r0, #SH_QSPI_SPDR]
272 subs r12, #1
273 bne 6b
274
275 7: subs r6, r11
276 bne prepcopy
277
278 mov pc, lr
279
280 sh_qspi_setup_command:
281 ldr r4, =SPIFLASH_SCRATCH_DATA
282 adr r5, _start
283 add r4, r5
284 and r12, r2, #0x0ff00000
285 lsr r12, #20
286 strb r12, [r4]
287 mov r12, r3
288 strb r12, [r4, #4]
289 lsr r12, #8
290 strb r12, [r4, #3]
291 lsr r12, #8
292 strb r12, [r4, #2]
293 lsr r12, #8
294 strb r12, [r4, #1]
295 lsr r12, #8
296 mov r5, #0x0
297 mov r6, #0x4
298 tst r2, (1 << 30)
299 movne r6, #0x5
300
301 mov pc, lr
302
303 SPIFLASH_READ_STATUS: .byte 0x05 /* Read Status Register */
304 SPIFLASH_WRITE_ENABLE: .byte 0x06 /* Write Enable */
305 SPIFLASH_NOOP: .byte 0x00
306 SPIFLASH_SCRATCH_DATA: .byte 0x00, 0x0, 0x0, 0x0, 0x0

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)