summaryrefslogtreecommitdiff
path: root/libhw/rp2040_hwspi.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhw/rp2040_hwspi.c')
-rw-r--r--libhw/rp2040_hwspi.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/libhw/rp2040_hwspi.c b/libhw/rp2040_hwspi.c
index ac46451..8dd49d6 100644
--- a/libhw/rp2040_hwspi.c
+++ b/libhw/rp2040_hwspi.c
@@ -18,6 +18,8 @@
#define IMPLEMENTATION_FOR_LIBHW_RP2040_HWSPI_H YES
#include <libhw/rp2040_hwspi.h>
+#include <libhw/generic/alarmclock.h>
+
#include "config.h"
#ifndef CONFIG_RP2040_SPI_DEBUG
@@ -39,6 +41,8 @@ void _rp2040_hwspi_init(struct rp2040_hwspi *self,
enum rp2040_hwspi_instance inst_num,
enum spi_mode mode,
uint baudrate_hz,
+ uint64_t min_delay_ns,
+ uint8_t bogus_data,
uint pin_miso,
uint pin_mosi,
uint pin_clk,
@@ -100,9 +104,12 @@ void _rp2040_hwspi_init(struct rp2040_hwspi *self,
gpio_set_dir(pin_cs, GPIO_OUT);
gpio_put(pin_cs, 1);
- /* Return. */
+ /* Initialize self. */
self->inst = inst;
+ self->min_delay_ns = min_delay_ns;
+ self->bogus_data = bogus_data;
self->pin_cs = pin_cs;
+ self->dead_until_ns = 0;
}
static void rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct duplex_iovec *iov, int iovcnt) {
@@ -113,6 +120,9 @@ static void rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct dupl
assert(iov);
assert(iovcnt);
+ uint64_t now = LO_CALL(bootclock, get_time_ns);
+ if (now < self->dead_until_ns)
+ sleep_until_ns(self->dead_until_ns);
gpio_put(self->pin_cs, 0);
/* TODO: Replace blocking reads+writes with DMA. */
for (int i = 0; i < iovcnt; i++) {
@@ -121,9 +131,10 @@ static void rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct dupl
else if (iov[i].iov_write_src)
spi_write_blocking(inst, iov[i].iov_write_src, iov[i].iov_len);
else if (iov[i].iov_read_dst)
- spi_read_blocking(inst, 0, iov[i].iov_read_dst, iov[i].iov_len);
+ spi_read_blocking(inst, self->bogus_data, iov[i].iov_read_dst, iov[i].iov_len);
else
assert_notreached("duplex_iovec is neither read nor write");
}
gpio_put(self->pin_cs, 1);
+ self->dead_until_ns = LO_CALL(bootclock, get_time_ns) + self->min_delay_ns;
}