1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <device/mmio.h>
6 #include <soc/addressmap.h>
8 #include "spi_internal.h"
10 static struct spi_ctrl
*spictrls
[] = {
11 (struct spi_ctrl
*)FU540_QSPI0
,
12 (struct spi_ctrl
*)FU540_QSPI1
,
13 (struct spi_ctrl
*)FU540_QSPI2
17 * Wait until SPI is ready for transmission and transmit byte.
19 static void spi_tx(volatile struct spi_ctrl
*spictrl
, uint8_t in
)
25 "amoor.w %0, %2, %1\n"
26 : "=r" (r
), "+A" (spictrl
->txdata
.raw_bits
)
31 while ((int32_t) spictrl
->txdata
.raw_bits
< 0)
33 spictrl
->txdata
.data
= in
;
38 * Wait until SPI receive queue has data and read byte.
40 static uint8_t spi_rx(volatile struct spi_ctrl
*spictrl
)
43 while ((out
= (int32_t) spictrl
->rxdata
.raw_bits
) < 0)
48 static int spi_claim_bus_(const struct spi_slave
*slave
)
50 struct spi_ctrl
*spictrl
= spictrls
[slave
->bus
];
51 spi_reg_csmode csmode
;
53 csmode
.mode
= FU540_SPI_CSMODE_HOLD
;
54 write32(&spictrl
->csmode
.raw_bits
, csmode
.raw_bits
);
58 static void spi_release_bus_(const struct spi_slave
*slave
)
60 struct spi_ctrl
*spictrl
= spictrls
[slave
->bus
];
61 spi_reg_csmode csmode
;
63 csmode
.mode
= FU540_SPI_CSMODE_OFF
;
64 write32(&spictrl
->csmode
.raw_bits
, csmode
.raw_bits
);
67 static int spi_xfer_(const struct spi_slave
*slave
,
68 const void *dout
, size_t bytesout
,
69 void *din
, size_t bytesin
)
71 struct spi_ctrl
*spictrl
= spictrls
[slave
->bus
];
73 fmt
.raw_bits
= read32(&spictrl
->fmt
.raw_bits
);
74 if (fmt
.proto
== FU540_SPI_PROTO_S
) {
75 /* working in full-duplex mode
76 * receiving data needs to be triggered by sending data */
77 while (bytesout
|| bytesin
) {
80 out
= *(uint8_t *)dout
++;
86 *(uint8_t *)din
++ = in
;
91 /* Working in half duplex
92 * send and receive can be done separately */
98 spi_tx(spictrl
, *(uint8_t *)dout
++);
105 *(uint8_t *)din
++ = spi_rx(spictrl
);
113 static int spi_setup_(const struct spi_slave
*slave
)
115 spi_reg_sckmode sckmode
;
116 spi_reg_csmode csmode
;
119 if ((slave
->bus
> 2) || (slave
->cs
!= 0))
122 struct spi_ctrl
*spictrl
= spictrls
[slave
->bus
];
124 write32(&spictrl
->sckdiv
, spi_min_clk_divisor(clock_get_tlclk_khz(),
127 sckmode
.raw_bits
= 0;
128 sckmode
.pha
= FU540_SPI_PHA_LOW
;
129 sckmode
.pol
= FU540_SPI_POL_LEADING
;
130 write32(&spictrl
->sckmode
.raw_bits
, sckmode
.raw_bits
);
132 write32(&spictrl
->csdef
, 0xffffffff);
135 csmode
.mode
= FU540_SPI_CSMODE_AUTO
;
136 write32(&spictrl
->csmode
.raw_bits
, csmode
.raw_bits
);
139 fmt
.proto
= FU540_SPI_PROTO_S
;
140 fmt
.endian
= FU540_SPI_ENDIAN_BIG
;
143 write32(&spictrl
->fmt
.raw_bits
, fmt
.raw_bits
);
148 struct spi_ctrlr fu540_spi_ctrlr
= {
151 .claim_bus
= spi_claim_bus_
,
152 .release_bus
= spi_release_bus_
,
155 const struct spi_ctrlr_buses spi_ctrlr_bus_map
[] = {
159 .ctrlr
= &fu540_spi_ctrlr
,
163 const size_t spi_ctrlr_bus_map_count
= ARRAY_SIZE(spi_ctrlr_bus_map
);
165 int fu540_spi_setup(unsigned int bus
, unsigned int cs
,
166 struct spi_slave
*slave
,
167 struct fu540_spi_config
*config
)
169 spi_reg_sckmode sckmode
;
170 spi_reg_csmode csmode
;
173 if ((bus
> 2) || (cs
!= 0))
176 if ((config
->pha
> 1)
178 || (config
->protocol
> 2)
179 || (config
->endianness
> 1)
180 || (config
->bits_per_frame
> 8))
185 slave
->ctrlr
= &fu540_spi_ctrlr
;
187 struct spi_ctrl
*spictrl
= spictrls
[slave
->bus
];
189 write32(&spictrl
->sckdiv
, spi_min_clk_divisor(clock_get_tlclk_khz(),
190 config
->freq
/ 1000));
192 sckmode
.raw_bits
= 0;
193 sckmode
.pha
= config
->pha
;
194 sckmode
.pol
= config
->pol
;
195 write32(&spictrl
->sckmode
.raw_bits
, sckmode
.raw_bits
);
197 write32(&spictrl
->csdef
, 0xffffffff);
200 csmode
.mode
= FU540_SPI_CSMODE_AUTO
;
201 write32(&spictrl
->csmode
.raw_bits
, csmode
.raw_bits
);
204 fmt
.proto
= config
->protocol
;
205 fmt
.endian
= config
->endianness
;
207 fmt
.len
= config
->bits_per_frame
;
208 write32(&spictrl
->fmt
.raw_bits
, fmt
.raw_bits
);
214 const struct spi_slave
*slave
,
215 const struct fu540_spi_mmap_config
*config
)
223 if ((config
->cmd_en
> 1)
224 || (config
->addr_len
> 4)
225 || (config
->pad_cnt
> 15)
226 || (config
->cmd_proto
> 2)
227 || (config
->addr_proto
> 2)
228 || (config
->data_proto
> 2)
229 || (config
->cmd_code
> 255)
230 || (config
->pad_code
> 255))
233 struct spi_ctrl
*spictrl
= spictrls
[slave
->bus
];
235 /* disable direct memory-mapped spi flash mode */
238 write32(&spictrl
->fctrl
.raw_bits
, fctrl
.raw_bits
);
240 /* reset spi flash chip */
241 spi_tx(spictrl
, 0x66);
242 spi_tx(spictrl
, 0x99);
244 /* Pass the information of the flash read operation to the spi
247 ffmt
.cmd_en
= config
->cmd_en
;
248 ffmt
.addr_len
= config
->addr_len
;
249 ffmt
.pad_cnt
= config
->pad_cnt
;
250 ffmt
.command_proto
= config
->cmd_proto
;
251 ffmt
.addr_proto
= config
->addr_proto
;
252 ffmt
.data_proto
= config
->data_proto
;
253 ffmt
.command_code
= config
->cmd_code
;
254 ffmt
.pad_code
= config
->pad_code
;
255 write32(&spictrl
->ffmt
.raw_bits
, ffmt
.raw_bits
);
257 /* enable direct memory-mapped spi flash mode */
260 write32(&spictrl
->fctrl
.raw_bits
, fctrl
.raw_bits
);