1 /* SPDX-License-Identifier: GPL-2.0-only */
4 * Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
7 #include <device/mmio.h>
9 #include <console/console.h>
11 #include <soc/addressmap.h>
13 #include <soc/clock.h>
14 #include <spi-generic.h>
15 #include <spi_flash.h>
18 union cavium_spi_cfg
{
31 u64 csena
: 4; /* Must be one */
37 union cavium_spi_sts
{
63 union cavium_spi_cfg cfg
;
64 union cavium_spi_sts sts
;
65 union cavium_spi_tx tx
;
76 check_member(cavium_spi
, cfg
, 0);
77 check_member(cavium_spi
, sts
, 0x8);
78 check_member(cavium_spi
, tx
, 0x10);
79 check_member(cavium_spi
, dat
[7], 0xb8);
81 struct cavium_spi_slave
{
82 struct cavium_spi
*regs
;
86 #define SPI_TIMEOUT_US 5000
88 static struct cavium_spi_slave cavium_spi_slaves
[] = {
90 .regs
= (struct cavium_spi
*)MPI_PF_BAR0
,
95 static struct cavium_spi_slave
*to_cavium_spi(const struct spi_slave
*slave
)
97 assert(slave
->bus
< ARRAY_SIZE(cavium_spi_slaves
));
98 return &cavium_spi_slaves
[slave
->bus
];
102 * Enable the SPI controller. Pins are driven.
104 * @param bus The SPI bus to operate on
106 void spi_enable(const size_t bus
)
108 union cavium_spi_cfg cfg
;
110 assert(bus
< ARRAY_SIZE(cavium_spi_slaves
));
111 if (bus
>= ARRAY_SIZE(cavium_spi_slaves
))
114 struct cavium_spi
*regs
= cavium_spi_slaves
[bus
].regs
;
116 cfg
.u
= read64(®s
->cfg
);
119 write64(®s
->cfg
, cfg
.u
);
123 * Disable the SPI controller. Pins are tristated.
125 * @param bus The SPI bus to operate on
127 void spi_disable(const size_t bus
)
129 union cavium_spi_cfg cfg
;
131 assert(bus
< ARRAY_SIZE(cavium_spi_slaves
));
132 if (bus
>= ARRAY_SIZE(cavium_spi_slaves
))
135 struct cavium_spi
*regs
= cavium_spi_slaves
[bus
].regs
;
137 cfg
.u
= read64(®s
->cfg
);
140 write64(®s
->cfg
, cfg
.u
);
144 * Set SPI Chip select line and level if asserted.
146 * @param bus The SPI bus to operate on
147 * @param chip_select The chip select pin to use (0 - 3)
148 * @param assert_is_low CS pin state is low when asserted
150 void spi_set_cs(const size_t bus
,
151 const size_t chip_select
,
152 const size_t assert_is_low
)
154 union cavium_spi_cfg cfg
;
156 assert(bus
< ARRAY_SIZE(cavium_spi_slaves
));
157 if (bus
>= ARRAY_SIZE(cavium_spi_slaves
))
160 cavium_spi_slaves
[bus
].cs
= chip_select
& 0x3;
161 struct cavium_spi
*regs
= cavium_spi_slaves
[bus
].regs
;
163 cfg
.u
= read64(®s
->cfg
);
165 cfg
.s
.cshi
= !assert_is_low
;
166 write64(®s
->cfg
, cfg
.u
);
168 //FIXME: CS2/3: Change pin mux here
172 * Set SPI clock frequency.
174 * @param bus The SPI bus to operate on
175 * @param speed_hz The SPI frequency in Hz
176 * @param idle_low The SPI clock idles low
177 * @param idle_cycles Number of CLK cycles between two commands (0 - 3)
180 void spi_set_clock(const size_t bus
,
181 const size_t speed_hz
,
182 const size_t idle_low
,
183 const size_t idle_cycles
)
185 union cavium_spi_cfg cfg
;
187 assert(bus
< ARRAY_SIZE(cavium_spi_slaves
));
188 if (bus
>= ARRAY_SIZE(cavium_spi_slaves
))
191 struct cavium_spi
*regs
= cavium_spi_slaves
[bus
].regs
;
192 const uint64_t sclk
= thunderx_get_io_clock();
194 cfg
.u
= read64(®s
->cfg
);
197 cfg
.s
.idlelow
= !!idle_low
;
198 cfg
.s
.idleclks
= idle_cycles
& 0x3;
199 cfg
.s
.clkdiv
= MIN(sclk
/ (2ULL * speed_hz
), 0x1fff);
200 write64(®s
->cfg
, cfg
.u
);
202 printk(BIOS_DEBUG
, "SPI: set clock to %lld kHz\n",
203 (sclk
/ (2ULL * cfg
.s
.clkdiv
)) >> 10);
207 * Get current SPI clock frequency in Hz.
209 * @param bus The SPI bus to operate on
211 uint64_t spi_get_clock(const size_t bus
)
213 union cavium_spi_cfg cfg
;
215 assert(bus
< ARRAY_SIZE(cavium_spi_slaves
));
216 if (bus
>= ARRAY_SIZE(cavium_spi_slaves
))
219 struct cavium_spi
*regs
= cavium_spi_slaves
[bus
].regs
;
220 const uint64_t sclk
= thunderx_get_io_clock();
222 cfg
.u
= read64(®s
->cfg
);
224 return (sclk
/ (2ULL * cfg
.s
.clkdiv
));
228 * Set SPI LSB/MSB first.
230 * @param bus The SPI bus to operate on
231 * @param lsb_first The SPI operates LSB first
234 void spi_set_lsbmsb(const size_t bus
, const size_t lsb_first
)
236 union cavium_spi_cfg cfg
;
238 assert(bus
< ARRAY_SIZE(cavium_spi_slaves
));
239 if (bus
>= ARRAY_SIZE(cavium_spi_slaves
))
242 struct cavium_spi
*regs
= cavium_spi_slaves
[bus
].regs
;
244 cfg
.u
= read64(®s
->cfg
);
246 cfg
.s
.lsbfirst
= !!lsb_first
;
247 write64(®s
->cfg
, cfg
.u
);
251 * Init SPI with custom parameters and enable SPI controller.
253 * @param bus The SPI bus to operate on
254 * @param speed_hz The SPI frequency in Hz
255 * @param idle_low The SPI clock idles low
256 * @param idle_cycles Number of CLK cycles between two commands (0 - 3)
257 * @param lsb_first The SPI operates LSB first
258 * @param chip_select The chip select pin to use (0 - 3)
259 * @param assert_is_low CS pin state is low when asserted
261 void spi_init_custom(const size_t bus
,
262 const size_t speed_hz
,
263 const size_t idle_low
,
264 const size_t idle_cycles
,
265 const size_t lsb_first
,
266 const size_t chip_select
,
267 const size_t assert_is_low
)
270 spi_set_clock(bus
, speed_hz
, idle_low
, idle_cycles
);
271 spi_set_lsbmsb(bus
, lsb_first
);
272 spi_set_cs(bus
, chip_select
, assert_is_low
);
277 * Init all SPI controllers with default values and enable all SPI controller.
282 for (size_t i
= 0; i
< ARRAY_SIZE(cavium_spi_slaves
); i
++) {
284 spi_set_clock(i
, 12500000, 0, 0);
285 spi_set_lsbmsb(i
, 0);
291 static int cavium_spi_wait(struct cavium_spi
*regs
)
294 union cavium_spi_sts sts
;
296 stopwatch_init_usecs_expire(&sw
, SPI_TIMEOUT_US
);
298 sts
.u
= read64(®s
->sts
);
301 } while (!stopwatch_expired(&sw
));
302 printk(BIOS_DEBUG
, "SPI: Timed out after %uus\n", SPI_TIMEOUT_US
);
306 static int do_xfer(const struct spi_slave
*slave
, struct spi_op
*vector
,
309 struct cavium_spi
*regs
= to_cavium_spi(slave
)->regs
;
310 uint8_t *out_buf
= (uint8_t *)vector
->dout
;
311 size_t bytesout
= vector
->bytesout
;
312 uint8_t *in_buf
= (uint8_t *)vector
->din
;
313 size_t bytesin
= vector
->bytesin
;
314 union cavium_spi_sts sts
;
315 union cavium_spi_tx tx
;
318 * The CN81xx SPI controller is half-duplex and has 8 data registers.
319 * If >8 bytes remain in the transfer then we must set LEAVECS = 1 so
320 * that the /CS remains asserted. Once <=8 bytes remain we must set
321 * LEAVECS = 0 so that /CS is de-asserted, thus completing the transfer.
324 size_t out_now
= MIN(bytesout
, 8);
327 for (i
= 0; i
< out_now
; i
++)
328 write64(®s
->dat
[i
], out_buf
[i
] & 0xff);
331 tx
.s
.csid
= to_cavium_spi(slave
)->cs
;
332 if (leavecs
|| ((bytesout
> 8) || bytesin
))
334 /* number of bytes to transmit goes in both TXNUM and TOTNUM */
335 tx
.s
.totnum
= out_now
;
336 tx
.s
.txnum
= out_now
;
337 write64(®s
->tx
, tx
.u
);
340 if (cavium_spi_wait(regs
) < 0)
348 size_t in_now
= MIN(bytesin
, 8);
352 tx
.s
.csid
= to_cavium_spi(slave
)->cs
;
353 if (leavecs
|| (bytesin
> 8))
355 tx
.s
.totnum
= in_now
;
356 write64(®s
->tx
, tx
.u
);
359 if (cavium_spi_wait(regs
) < 0)
362 sts
.u
= read64(®s
->sts
);
363 if (sts
.s
.rxnum
!= in_now
) {
365 "SPI: Incorrect number of bytes received: %u.\n",
370 for (i
= 0; i
< in_now
; i
++) {
371 *in_buf
= (uint8_t)((read64(®s
->dat
[i
]) & 0xff));
380 static int spi_ctrlr_xfer_vector(const struct spi_slave
*slave
,
381 struct spi_op vectors
[], size_t count
)
385 for (i
= 0; i
< count
; i
++) {
386 if (do_xfer(slave
, &vectors
[i
], count
- 1 == i
? 0 : 1)) {
388 "SPI: Failed to transfer %zu vectors.\n", count
);
395 static const struct spi_ctrlr spi_ctrlr
= {
396 .xfer_vector
= spi_ctrlr_xfer_vector
,
397 .max_xfer_size
= SPI_CTRLR_DEFAULT_MAX_XFER_SIZE
,
400 const struct spi_ctrlr_buses spi_ctrlr_bus_map
[] = {
404 .bus_end
= ARRAY_SIZE(cavium_spi_slaves
) - 1,
407 const size_t spi_ctrlr_bus_map_count
= ARRAY_SIZE(spi_ctrlr_bus_map
);