15 #include "spi_host_regs.h"
23 const
void *src, uint16_t len);
33 mmio_region_read32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET);
35 spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET,
42 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
50 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
53 }
while (txqd != 0 || rxqd != 0);
57 spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET,
61 static void spi_host_enable(
const dif_spi_host_t *spi_host,
bool enable) {
63 mmio_region_read32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET);
65 spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET,
71 if (spi_host == NULL) {
80 if (divider & ~(uint32_t)SPI_HOST_CONFIGOPTS_CLKDIV_0_MASK) {
84 spi_host_reset(spi_host);
89 config.chip_select.idle);
91 config.chip_select.trail);
93 config.chip_select.lead);
98 mmio_region_write32(spi_host->
base_addr, SPI_HOST_CONFIGOPTS_REG_OFFSET, reg);
100 reg = mmio_region_read32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET);
105 mmio_region_write32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET, reg);
107 spi_host_enable(spi_host,
true);
113 if (spi_host == NULL) {
118 mmio_region_read32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET);
120 spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET,
130 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
139 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
141 }
while (txqd == SPI_HOST_PARAM_TX_DEPTH);
148 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
155 uint8_t *src = (uint8_t *)srcaddr;
156 wait_tx_fifo(spi_host);
157 mmio_region_write8(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET, *src);
160 static inline void tx_fifo_write32(
const dif_spi_host_t *spi_host,
162 wait_tx_fifo(spi_host);
163 uint32_t val =
read_32((
const void *)srcaddr);
164 mmio_region_write32(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET, val);
168 const void *src, uint16_t len) {
169 uintptr_t ptr = (uintptr_t)src;
170 if (spi_host == NULL || (src == NULL && len > 0)) {
176 tx_fifo_write8(spi_host, ptr);
183 tx_fifo_write32(spi_host, ptr);
190 tx_fifo_write8(spi_host, ptr);
200 uint8_t
alignas(uint64_t) data[8];
203 static void enqueue_byte(
queue_t *
queue, uint8_t data) {
207 static void enqueue_word(
queue_t *
queue, uint32_t data) {
208 if (
queue->length % (int32_t)
sizeof(uint32_t) == 0) {
212 for (
size_t i = 0; i <
sizeof(uint32_t); ++i) {
213 enqueue_byte(
queue, (uint8_t)data);
220 uint8_t val =
queue->data[0];
236 if (spi_host == NULL || (dst == NULL && len > 0)) {
240 uintptr_t ptr = (uintptr_t)dst;
248 if (
queue.length < 1) {
249 wait_rx_fifo(spi_host);
251 SPI_HOST_RXDATA_REG_OFFSET));
253 uint8_t *p = (uint8_t *)ptr;
254 *p = dequeue_byte(&
queue);
261 if (
queue.length < 4) {
262 wait_rx_fifo(spi_host);
264 SPI_HOST_RXDATA_REG_OFFSET));
273 if (
queue.length < 1) {
274 wait_rx_fifo(spi_host);
276 SPI_HOST_RXDATA_REG_OFFSET));
278 uint8_t *p = (uint8_t *)ptr;
279 *p = dequeue_byte(&
queue);
287 static void write_command_reg(
const dif_spi_host_t *spi_host, uint16_t length,
297 mmio_region_write32(spi_host->
base_addr, SPI_HOST_COMMAND_REG_OFFSET, reg);
302 wait_tx_fifo(spi_host);
303 mmio_region_write8(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET,
304 segment->opcode.opcode);
311 wait_tx_fifo(spi_host);
317 mmio_region_write32(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET,
322 mmio_region_write32(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET,
325 write_command_reg(spi_host, length, segment->address.width,
331 if (segment->dummy.length > 0) {
335 write_command_reg(spi_host, (uint16_t)segment->dummy.length,
344 switch (segment->
type) {
346 write_command_reg(spi_host, (uint16_t)segment->tx.length,
349 spi_host_fifo_write_alias(spi_host, segment->tx.buf,
350 (uint16_t)segment->tx.length);
353 write_command_reg(spi_host, (uint16_t)segment->bidir.length,
356 spi_host_fifo_write_alias(spi_host, segment->bidir.txbuf,
357 (uint16_t)segment->bidir.length);
360 write_command_reg(spi_host, (uint16_t)segment->rx.length,
378 mmio_region_write32(spi_host->
base_addr, SPI_HOST_CSID_REG_OFFSET, csid);
382 for (
size_t i = 0; i < length; ++i) {
383 bool last_segment = i == length - 1;
384 wait_ready(spi_host);
386 switch (segment->
type) {
388 issue_opcode(spi_host, segment, last_segment);
391 issue_address(spi_host, segment, last_segment);
394 issue_dummy(spi_host, segment, last_segment);
399 dif_result_t error = issue_data_phase(spi_host, segment, last_segment);
411 for (
size_t i = 0; i < length; ++i) {
413 switch (segment->
type) {
415 spi_host_fifo_read_alias(spi_host, segment->rx.buf,
416 (uint16_t)segment->rx.length);
419 spi_host_fifo_read_alias(spi_host, segment->bidir.rxbuf,
420 (uint16_t)segment->bidir.length);
437 mmio_region_read32(spi_host->
base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET);
443 mmio_region_write32(spi_host->
base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET,
450 if (spi_host == NULL || events == NULL) {
455 mmio_region_read32(spi_host->
base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET);
461 if (spi_host == NULL ||
status == NULL) {
466 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
478 status->least_significant_first =
495 if (spi_host == NULL) {
498 write_command_reg(spi_host, length, speed, direction, last_segment);
510 mmio_region_read32(spi_host->
base_addr, SPI_HOST_ERROR_ENABLE_REG_OFFSET);
516 mmio_region_write32(spi_host->
base_addr, SPI_HOST_ERROR_ENABLE_REG_OFFSET,
523 if (spi_host == NULL || errors == NULL) {
528 mmio_region_read32(spi_host->
base_addr, SPI_HOST_ERROR_ENABLE_REG_OFFSET);
534 if (spi_host == NULL || error == NULL) {
539 mmio_region_read32(spi_host->
base_addr, SPI_HOST_ERROR_STATUS_REG_OFFSET);
545 if (spi_host == NULL) {
552 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);