78eb1e81872d75afc79f6b711a791596a3a98e79
[fw/openocd] / 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