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,
36 bitfield_bit32_write(reg, SPI_HOST_CONTROL_SW_RST_BIT,
true));
42 mmio_region_read32(spi_host->base_addr, SPI_HOST_STATUS_REG_OFFSET);
43 active = bitfield_bit32_read(reg, SPI_HOST_STATUS_ACTIVE_BIT);
50 mmio_region_read32(spi_host->base_addr, SPI_HOST_STATUS_REG_OFFSET);
51 txqd = bitfield_field32_read(reg, SPI_HOST_STATUS_TXQD_FIELD);
52 rxqd = bitfield_field32_read(reg, SPI_HOST_STATUS_RXQD_FIELD);
53 }
while (txqd != 0 || rxqd != 0);
57 spi_host->base_addr, SPI_HOST_CONTROL_REG_OFFSET,
58 bitfield_bit32_write(0, SPI_HOST_CONTROL_SW_RST_BIT,
false));
61static 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,
66 bitfield_bit32_write(reg, SPI_HOST_CONTROL_SPIEN_BIT, enable));
71 if (spi_host == NULL) {
80 if (divider & ~(uint32_t)SPI_HOST_CONFIGOPTS_CLKDIV_MASK) {
84 spi_host_reset(spi_host);
86 reg = bitfield_field32_write(reg, SPI_HOST_CONFIGOPTS_CLKDIV_FIELD, divider);
87 reg = bitfield_field32_write(reg, SPI_HOST_CONFIGOPTS_CSNIDLE_FIELD,
88 config.chip_select.idle);
89 reg = bitfield_field32_write(reg, SPI_HOST_CONFIGOPTS_CSNTRAIL_FIELD,
90 config.chip_select.trail);
91 reg = bitfield_field32_write(reg, SPI_HOST_CONFIGOPTS_CSNLEAD_FIELD,
92 config.chip_select.lead);
93 reg = bitfield_bit32_write(reg, SPI_HOST_CONFIGOPTS_FULLCYC_BIT,
95 reg = bitfield_bit32_write(reg, SPI_HOST_CONFIGOPTS_CPHA_BIT, config.
cpha);
96 reg = bitfield_bit32_write(reg, SPI_HOST_CONFIGOPTS_CPOL_BIT, config.
cpol);
97 mmio_region_write32(spi_host->
base_addr, SPI_HOST_CONFIGOPTS_REG_OFFSET, reg);
99 reg = mmio_region_read32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET);
100 reg = bitfield_field32_write(reg, SPI_HOST_CONTROL_TX_WATERMARK_FIELD,
102 reg = bitfield_field32_write(reg, SPI_HOST_CONTROL_RX_WATERMARK_FIELD,
104 mmio_region_write32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET, reg);
106 spi_host_enable(spi_host,
true);
112 if (spi_host == NULL) {
117 mmio_region_read32(spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET);
119 spi_host->
base_addr, SPI_HOST_CONTROL_REG_OFFSET,
120 bitfield_bit32_write(reg, SPI_HOST_CONTROL_OUTPUT_EN_BIT, enabled));
129 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
130 ready = bitfield_bit32_read(reg, SPI_HOST_STATUS_READY_BIT);
138 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
139 txqd = bitfield_field32_read(reg, SPI_HOST_STATUS_TXQD_FIELD);
140 }
while (txqd == SPI_HOST_PARAM_TX_DEPTH);
147 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
148 rxqd = bitfield_field32_read(reg, SPI_HOST_STATUS_RXQD_FIELD);
154 uint8_t *src = (uint8_t *)srcaddr;
155 wait_tx_fifo(spi_host);
156 mmio_region_write8(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET, *src);
161 wait_tx_fifo(spi_host);
162 uint32_t val = read_32((
const void *)srcaddr);
163 mmio_region_write32(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET, val);
167 const void *src, uint16_t len) {
168 uintptr_t ptr = (uintptr_t)src;
169 if (spi_host == NULL || (src == NULL && len > 0)) {
174 while (misalignment32_of(ptr) && len > 0) {
175 tx_fifo_write8(spi_host, ptr);
182 tx_fifo_write32(spi_host, ptr);
189 tx_fifo_write8(spi_host, ptr);
199 uint8_t
alignas(uint64_t) data[8];
202static void enqueue_byte(queue_t *
queue, uint8_t data) {
206static void enqueue_word(queue_t *
queue, uint32_t data) {
207 if (
queue->length % (int32_t)
sizeof(uint32_t) == 0) {
211 for (
size_t i = 0; i <
sizeof(uint32_t); ++i) {
212 enqueue_byte(
queue, (uint8_t)data);
218static uint8_t dequeue_byte(queue_t *
queue) {
219 uint8_t val =
queue->data[0];
220 uint64_t qword = read_64(
queue->data);
221 write_64(qword >> 8,
queue->data);
226static uint32_t dequeue_word(queue_t *
queue) {
227 uint32_t val = read_32(
queue->data);
228 write_32(read_32(
queue->data +
sizeof(uint32_t)),
queue->data);
235 if (spi_host == NULL || (dst == NULL && len > 0)) {
239 uintptr_t ptr = (uintptr_t)dst;
246 while (misalignment32_of(ptr) && len > 0) {
247 if (
queue.length < 1) {
248 wait_rx_fifo(spi_host);
250 SPI_HOST_RXDATA_REG_OFFSET));
252 uint8_t *p = (uint8_t *)ptr;
253 *p = dequeue_byte(&
queue);
260 if (
queue.length < 4) {
261 wait_rx_fifo(spi_host);
263 SPI_HOST_RXDATA_REG_OFFSET));
265 write_32(dequeue_word(&
queue), (
void *)ptr);
272 if (
queue.length < 1) {
273 wait_rx_fifo(spi_host);
275 SPI_HOST_RXDATA_REG_OFFSET));
277 uint8_t *p = (uint8_t *)ptr;
278 *p = dequeue_byte(&
queue);
286static void write_command_reg(
const dif_spi_host_t *spi_host, uint16_t length,
291 reg = bitfield_field32_write(reg, SPI_HOST_COMMAND_LEN_FIELD, length - 1);
292 reg = bitfield_field32_write(reg, SPI_HOST_COMMAND_SPEED_FIELD, speed);
294 bitfield_field32_write(reg, SPI_HOST_COMMAND_DIRECTION_FIELD, direction);
295 reg = bitfield_bit32_write(reg, SPI_HOST_COMMAND_CSAAT_BIT, !last_segment);
296 mmio_region_write32(spi_host->
base_addr, SPI_HOST_COMMAND_REG_OFFSET, reg);
301 wait_tx_fifo(spi_host);
302 mmio_region_write8(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET,
303 segment->opcode.opcode);
310 wait_tx_fifo(spi_host);
312 uint32_t address = bitfield_byteswap32(segment->address.address);
316 mmio_region_write32(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET,
321 mmio_region_write32(spi_host->
base_addr, SPI_HOST_TXDATA_REG_OFFSET,
324 write_command_reg(spi_host, length, segment->address.width,
330 if (segment->dummy.length > 0) {
334 write_command_reg(spi_host, (uint16_t)segment->dummy.length,
343 switch (segment->
type) {
345 write_command_reg(spi_host, (uint16_t)segment->tx.length,
348 spi_host_fifo_write_alias(spi_host, segment->tx.buf,
349 (uint16_t)segment->tx.length);
352 write_command_reg(spi_host, (uint16_t)segment->bidir.length,
355 spi_host_fifo_write_alias(spi_host, segment->bidir.txbuf,
356 (uint16_t)segment->bidir.length);
359 write_command_reg(spi_host, (uint16_t)segment->rx.length,
376 if (spi_host == NULL || segments == NULL) {
381 mmio_region_write32(spi_host->
base_addr, SPI_HOST_CSID_REG_OFFSET, csid);
385 for (
size_t i = 0; i < length; ++i) {
386 bool last_segment = i == length - 1;
387 wait_ready(spi_host);
389 switch (segment->
type) {
391 issue_opcode(spi_host, segment, last_segment);
394 issue_address(spi_host, segment, last_segment);
397 issue_dummy(spi_host, segment, last_segment);
402 dif_result_t error = issue_data_phase(spi_host, segment, last_segment);
420 dif_spi_host_start_transaction(spi_host, csid, segments, length));
423 for (
size_t i = 0; i < length; ++i) {
425 switch (segment->
type) {
427 spi_host_fifo_read_alias(spi_host, segment->rx.buf,
428 (uint16_t)segment->rx.length);
431 spi_host_fifo_read_alias(spi_host, segment->bidir.rxbuf,
432 (uint16_t)segment->bidir.length);
449 mmio_region_read32(spi_host->
base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET);
455 mmio_region_write32(spi_host->
base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET,
462 if (spi_host == NULL || events == NULL) {
467 mmio_region_read32(spi_host->
base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET);
472 dif_spi_host_status_t *
status) {
473 if (spi_host == NULL ||
status == NULL) {
478 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
480 status->ready = bitfield_bit32_read(reg, SPI_HOST_STATUS_READY_BIT);
481 status->active = bitfield_bit32_read(reg, SPI_HOST_STATUS_ACTIVE_BIT);
482 status->tx_empty = bitfield_bit32_read(reg, SPI_HOST_STATUS_TXEMPTY_BIT);
483 status->rx_empty = bitfield_bit32_read(reg, SPI_HOST_STATUS_RXEMPTY_BIT);
484 status->tx_full = bitfield_bit32_read(reg, SPI_HOST_STATUS_TXFULL_BIT);
485 status->rx_full = bitfield_bit32_read(reg, SPI_HOST_STATUS_RXFULL_BIT);
486 status->tx_water_mark = bitfield_bit32_read(reg, SPI_HOST_STATUS_TXWM_BIT);
487 status->rx_water_mark = bitfield_bit32_read(reg, SPI_HOST_STATUS_RXWM_BIT);
488 status->tx_stall = bitfield_bit32_read(reg, SPI_HOST_STATUS_TXSTALL_BIT);
489 status->rx_stall = bitfield_bit32_read(reg, SPI_HOST_STATUS_RXSTALL_BIT);
490 status->least_significant_first =
491 bitfield_bit32_read(reg, SPI_HOST_STATUS_BYTEORDER_BIT);
493 bitfield_field32_read(reg, SPI_HOST_STATUS_TXQD_FIELD);
495 bitfield_field32_read(reg, SPI_HOST_STATUS_RXQD_FIELD);
497 bitfield_field32_read(reg, SPI_HOST_STATUS_CMDQD_FIELD);
507 if (spi_host == NULL) {
510 write_command_reg(spi_host, length, speed, direction, last_segment);
522 mmio_region_read32(spi_host->
base_addr, SPI_HOST_ERROR_ENABLE_REG_OFFSET);
528 mmio_region_write32(spi_host->
base_addr, SPI_HOST_ERROR_ENABLE_REG_OFFSET,
535 if (spi_host == NULL || errors == NULL) {
540 mmio_region_read32(spi_host->
base_addr, SPI_HOST_ERROR_ENABLE_REG_OFFSET);
546 if (spi_host == NULL || error == NULL) {
551 mmio_region_read32(spi_host->
base_addr, SPI_HOST_ERROR_STATUS_REG_OFFSET);
557 if (spi_host == NULL) {
564 mmio_region_read32(spi_host->
base_addr, SPI_HOST_STATUS_REG_OFFSET);
565 active = bitfield_bit32_read(reg, SPI_HOST_STATUS_ACTIVE_BIT);