15#include "hw/top/spi_host_regs.h"
24 const void *src, uint16_t len) {
25 return dif_spi_host_fifo_write(spi_host, src, len);
31 return dif_spi_host_fifo_read(spi_host, dst, len);
37 const
void *src, uint16_t len);
48 mmio_region_read32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET);
50 spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET,
51 bitfield_bit32_write(reg, SPI_HOST_CONTROL_SW_RST_BIT,
true));
57 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
58 active = bitfield_bit32_read(reg, SPI_HOST_STATUS_ACTIVE_BIT);
65 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
66 txqd = bitfield_field32_read(reg, SPI_HOST_STATUS_TXQD_FIELD);
67 rxqd = bitfield_field32_read(reg, SPI_HOST_STATUS_RXQD_FIELD);
68 }
while (txqd != 0 || rxqd != 0);
72 spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET,
73 bitfield_bit32_write(0, SPI_HOST_CONTROL_SW_RST_BIT,
false));
76static void spi_host_enable(
const dif_spi_host_t *spi_host,
bool enable) {
78 mmio_region_read32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET);
80 spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET,
81 bitfield_bit32_write(reg, SPI_HOST_CONTROL_SPIEN_BIT, enable));
86 if (spi_host == NULL) {
95 if (divider & ~(uint32_t)SPI_HOST_CONFIGOPTS_CLKDIV_MASK) {
99 spi_host_reset(spi_host);
101 reg = bitfield_field32_write(reg, SPI_HOST_CONFIGOPTS_CLKDIV_FIELD, divider);
102 reg = bitfield_field32_write(reg, SPI_HOST_CONFIGOPTS_CSNIDLE_FIELD,
103 config.chip_select.idle);
104 reg = bitfield_field32_write(reg, SPI_HOST_CONFIGOPTS_CSNTRAIL_FIELD,
105 config.chip_select.trail);
106 reg = bitfield_field32_write(reg, SPI_HOST_CONFIGOPTS_CSNLEAD_FIELD,
107 config.chip_select.lead);
108 reg = bitfield_bit32_write(reg, SPI_HOST_CONFIGOPTS_FULLCYC_BIT,
110 reg = bitfield_bit32_write(reg, SPI_HOST_CONFIGOPTS_CPHA_BIT, config.
cpha);
111 reg = bitfield_bit32_write(reg, SPI_HOST_CONFIGOPTS_CPOL_BIT, config.
cpol);
112 mmio_region_write32(spi_host->
base_addr, SPI_HOST_CONFIGOPTS_REG_OFFSET, reg);
114 reg = mmio_region_read32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET);
115 reg = bitfield_field32_write(reg, SPI_HOST_CONTROL_TX_WATERMARK_FIELD,
117 reg = bitfield_field32_write(reg, SPI_HOST_CONTROL_RX_WATERMARK_FIELD,
119 mmio_region_write32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET, reg);
121 spi_host_enable(spi_host,
true);
127 if (spi_host == NULL) {
132 mmio_region_read32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET);
134 spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET,
135 bitfield_bit32_write(reg, SPI_HOST_CONTROL_OUTPUT_EN_BIT, enabled));
144 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
145 ready = bitfield_bit32_read(reg, SPI_HOST_STATUS_READY_BIT);
153 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
154 txqd = bitfield_field32_read(reg, SPI_HOST_STATUS_TXQD_FIELD);
155 }
while (txqd == SPI_HOST_PARAM_TX_DEPTH);
162 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
163 rxqd = bitfield_field32_read(reg, SPI_HOST_STATUS_RXQD_FIELD);
169 uint8_t *src = (uint8_t *)srcaddr;
170 wait_tx_fifo(spi_host);
171 mmio_region_write8(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET, *src);
176 wait_tx_fifo(spi_host);
177 uint32_t val = read_32((
const void *)srcaddr);
178 mmio_region_write32(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET, val);
182 const void *src, uint16_t len) {
183 uintptr_t ptr = (uintptr_t)src;
184 if (spi_host == NULL || (src == NULL && len > 0)) {
189 while (misalignment32_of(ptr) && len > 0) {
190 tx_fifo_write8(spi_host, ptr);
197 tx_fifo_write32(spi_host, ptr);
204 tx_fifo_write8(spi_host, ptr);
214 uint8_t
alignas(uint64_t) data[8];
217static void enqueue_byte(queue_t *
queue, uint8_t data) {
221static void enqueue_word(queue_t *
queue, uint32_t data) {
222 if (
queue->length % (int32_t)
sizeof(uint32_t) == 0) {
226 for (
size_t i = 0; i <
sizeof(uint32_t); ++i) {
227 enqueue_byte(
queue, (uint8_t)data);
233static uint8_t dequeue_byte(queue_t *
queue) {
234 uint8_t val =
queue->data[0];
235 uint64_t qword = read_64(
queue->data);
236 write_64(qword >> 8,
queue->data);
241static uint32_t dequeue_word(queue_t *
queue) {
242 uint32_t val = read_32(
queue->data);
243 write_32(read_32(
queue->data +
sizeof(uint32_t)),
queue->data);
250 if (spi_host == NULL || (dst == NULL && len > 0)) {
254 uintptr_t ptr = (uintptr_t)dst;
261 while (misalignment32_of(ptr) && len > 0) {
262 if (
queue.length < 1) {
263 wait_rx_fifo(spi_host);
265 SPI_HOST_RXDATA_REG_OFFSET));
267 uint8_t *p = (uint8_t *)ptr;
268 *p = dequeue_byte(&
queue);
275 if (
queue.length < 4) {
276 wait_rx_fifo(spi_host);
278 SPI_HOST_RXDATA_REG_OFFSET));
280 write_32(dequeue_word(&
queue), (
void *)ptr);
287 if (
queue.length < 1) {
288 wait_rx_fifo(spi_host);
290 SPI_HOST_RXDATA_REG_OFFSET));
292 uint8_t *p = (uint8_t *)ptr;
293 *p = dequeue_byte(&
queue);
301static void write_command_reg(
const dif_spi_host_t *spi_host, uint16_t length,
306 reg = bitfield_field32_write(reg, SPI_HOST_COMMAND_LEN_FIELD, length - 1);
307 reg = bitfield_field32_write(reg, SPI_HOST_COMMAND_SPEED_FIELD, speed);
309 bitfield_field32_write(reg, SPI_HOST_COMMAND_DIRECTION_FIELD, direction);
310 reg = bitfield_bit32_write(reg, SPI_HOST_COMMAND_CSAAT_BIT, !last_segment);
311 mmio_region_write32(spi_host->
base_addr, SPI_HOST_COMMAND_REG_OFFSET, reg);
316 wait_tx_fifo(spi_host);
317 mmio_region_write8(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET,
318 segment->opcode.opcode);
325 wait_tx_fifo(spi_host);
327 uint32_t address = bitfield_byteswap32(segment->address.address);
331 mmio_region_write32(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET,
336 mmio_region_write32(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET,
339 write_command_reg(spi_host, length, segment->address.width,
345 if (segment->dummy.length > 0) {
349 write_command_reg(spi_host, (uint16_t)segment->dummy.length,
358 switch (segment->
type) {
360 write_command_reg(spi_host, (uint16_t)segment->tx.length,
363 spi_host_fifo_write_alias(spi_host, segment->tx.buf,
364 (uint16_t)segment->tx.length);
367 write_command_reg(spi_host, (uint16_t)segment->bidir.length,
370 spi_host_fifo_write_alias(spi_host, segment->bidir.txbuf,
371 (uint16_t)segment->bidir.length);
374 write_command_reg(spi_host, (uint16_t)segment->rx.length,
391 if (spi_host == NULL || segments == NULL) {
396 mmio_region_write32(spi_host->
base_addr, SPI_HOST_CSID_REG_OFFSET, csid);
400 for (
size_t i = 0; i < length; ++i) {
401 bool last_segment = i == length - 1;
402 wait_ready(spi_host);
404 switch (segment->
type) {
406 issue_opcode(spi_host, segment, last_segment);
409 issue_address(spi_host, segment, last_segment);
412 issue_dummy(spi_host, segment, last_segment);
417 dif_result_t error = issue_data_phase(spi_host, segment, last_segment);
435 dif_spi_host_start_transaction(spi_host, csid, segments, length));
438 for (
size_t i = 0; i < length; ++i) {
440 switch (segment->
type) {
442 spi_host_fifo_read_alias(spi_host, segment->rx.buf,
443 (uint16_t)segment->rx.length);
446 spi_host_fifo_read_alias(spi_host, segment->bidir.rxbuf,
447 (uint16_t)segment->bidir.length);
464 mmio_region_read32(spi_host->
base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET);
470 mmio_region_write32(spi_host->
base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET,
477 if (spi_host == NULL || events == NULL) {
482 mmio_region_read32(spi_host->
base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET);
487 dif_spi_host_status_t *
status) {
488 if (spi_host == NULL ||
status == NULL) {
493 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
495 status->ready = bitfield_bit32_read(reg, SPI_HOST_STATUS_READY_BIT);
496 status->active = bitfield_bit32_read(reg, SPI_HOST_STATUS_ACTIVE_BIT);
497 status->tx_empty = bitfield_bit32_read(reg, SPI_HOST_STATUS_TXEMPTY_BIT);
498 status->rx_empty = bitfield_bit32_read(reg, SPI_HOST_STATUS_RXEMPTY_BIT);
499 status->tx_full = bitfield_bit32_read(reg, SPI_HOST_STATUS_TXFULL_BIT);
500 status->rx_full = bitfield_bit32_read(reg, SPI_HOST_STATUS_RXFULL_BIT);
501 status->tx_water_mark = bitfield_bit32_read(reg, SPI_HOST_STATUS_TXWM_BIT);
502 status->rx_water_mark = bitfield_bit32_read(reg, SPI_HOST_STATUS_RXWM_BIT);
503 status->tx_stall = bitfield_bit32_read(reg, SPI_HOST_STATUS_TXSTALL_BIT);
504 status->rx_stall = bitfield_bit32_read(reg, SPI_HOST_STATUS_RXSTALL_BIT);
505 status->least_significant_first =
506 bitfield_bit32_read(reg, SPI_HOST_STATUS_BYTEORDER_BIT);
508 bitfield_field32_read(reg, SPI_HOST_STATUS_TXQD_FIELD);
510 bitfield_field32_read(reg, SPI_HOST_STATUS_RXQD_FIELD);
512 bitfield_field32_read(reg, SPI_HOST_STATUS_CMDQD_FIELD);
522 if (spi_host == NULL) {
525 write_command_reg(spi_host, length, speed, direction, last_segment);
537 mmio_region_read32(spi_host->
base_addr, SPI_HOST_ERROR_ENABLE_REG_OFFSET);
543 mmio_region_write32(spi_host->
base_addr, SPI_HOST_ERROR_ENABLE_REG_OFFSET,
550 if (spi_host == NULL || errors == NULL) {
555 mmio_region_read32(spi_host->
base_addr, SPI_HOST_ERROR_ENABLE_REG_OFFSET);
561 if (spi_host == NULL || error == NULL) {
566 mmio_region_read32(spi_host->
base_addr, SPI_HOST_ERROR_STATUS_REG_OFFSET);
572 if (spi_host == NULL) {
579 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
580 active = bitfield_bit32_read(reg, SPI_HOST_STATUS_ACTIVE_BIT);