diff options
Diffstat (limited to 'libhw/rp2040_hwspi.c')
-rw-r--r-- | libhw/rp2040_hwspi.c | 15 |
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; } |