summaryrefslogtreecommitdiff
path: root/cmd/sbc_harness/hw/rp2040_hwspi.c
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/sbc_harness/hw/rp2040_hwspi.c')
-rw-r--r--cmd/sbc_harness/hw/rp2040_hwspi.c123
1 files changed, 0 insertions, 123 deletions
diff --git a/cmd/sbc_harness/hw/rp2040_hwspi.c b/cmd/sbc_harness/hw/rp2040_hwspi.c
deleted file mode 100644
index 6742c60..0000000
--- a/cmd/sbc_harness/hw/rp2040_hwspi.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/* hw/rp2040_hwspi.c - `implements_spi` implementation for the RP2040's
- * ARM Primecell SSP (PL022) (implementation file)
- *
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
- * SPDX-Licence-Identifier: AGPL-3.0-or-later
- */
-
-#include <assert.h>
-
-#include <hardware/spi.h> /* pico-sdk:hardware_spi */
-#include <hardware/gpio.h> /* pico-sdk:hardware_gpio5 */
-
-#include <libmisc/vcall.h>
-
-#include "hw/rp2040_hwspi.h"
-
-static void rp2040_hwspi_readwritev(implements_spi *, const struct bidi_iovec *iov, int iovcnt);
-
-struct spi_vtable rp2040_hwspi_vtable = {
- .readwritev = rp2040_hwspi_readwritev,
-};
-
-void _rp2040_hwspi_init(struct rp2040_hwspi *self,
- enum rp2040_hwspi_instance inst_num,
- enum spi_mode mode,
- uint baudrate_hz,
- uint pin_miso,
- uint pin_mosi,
- uint pin_clk,
- uint pin_cs) {
- /* Be not weary: This is but 12 lines of actual code; and many
- * lines of comments and assert()s. */
- spi_inst_t *inst;
-
- assert(self);
- assert(baudrate_hz);
- assert(pin_miso != pin_mosi);
- assert(pin_miso != pin_clk);
- assert(pin_miso != pin_cs);
- assert(pin_mosi != pin_clk);
- assert(pin_mosi != pin_cs);
- assert(pin_clk != pin_cs);
-
- /* I know we called this "hwspi", but we're actually going to
- * disconnect the CS pin from the PL022 SSP and manually drive
- * it from software. This is because the PL022 has a maximum
- * of 16-bit frames, while we need to be able to do *at least*
- * 32-bit frames (and ideally, much larger). By managing it
- * ourselves, we can just keep CS pulled low extra-long,
- * making the frame extra-long. */
-
- /* Regarding the constraints on pin assignments: see the
- * RP2040 datasheet, table 2, in §1.4.3 "GPIO Functions". */
- switch (inst_num) {
- case RP2040_HWSPI_0:
- inst = spi0;
- assert(pin_miso == 0 || pin_miso == 4 || pin_miso == 16 || pin_miso == 20);
- /*assert(pin_cs == 1 || pin_cs == 5 || pin_cs == 17 || pin_cs == 21);*/
- assert(pin_clk == 2 || pin_clk == 6 || pin_clk == 18 || pin_clk == 22);
- assert(pin_mosi == 3 || pin_mosi == 7 || pin_mosi == 19 || pin_mosi == 23);
- break;
- case RP2040_HWSPI_1:
- inst = spi1;
- assert(pin_miso == 8 || pin_miso == 12 || pin_miso == 24 || pin_miso == 28);
- /*assert(pin_cs == 9 || pin_cs == 13 || pin_cs == 25 || pin_cs == 29);*/
- assert(pin_clk == 10 || pin_clk == 14 || pin_clk == 26);
- assert(pin_mosi == 11 || pin_mosi == 15 || pin_mosi == 27);
- break;
- default:
- assert(false);
- }
-
- spi_init(inst, baudrate_hz);
- spi_set_format(inst, 8,
- (mode & 0b10) ? SPI_CPOL_1 : SPI_CPOL_0,
- (mode & 0b01) ? SPI_CPHA_1 : SPI_CPHA_0,
- SPI_MSB_FIRST);
-
- /* Connect the pins to the PL022; set them each to "function
- * 1" (again, see the RP2040 datasheet, table 2, in §1.4.3
- * "GPIO Functions").
- *
- * ("GPIO_FUNC_SPI" is how the pico-sdk spells "function 1",
- * since on the RP2040 all of the "function 1" functions are
- * some part of SPI.) */
- gpio_set_function(pin_clk, GPIO_FUNC_SPI);
- gpio_set_function(pin_mosi, GPIO_FUNC_SPI);
- gpio_set_function(pin_miso, GPIO_FUNC_SPI);
-
- /* Initialize the CS pin for software control. */
- gpio_init(pin_cs);
- gpio_set_dir(pin_cs, GPIO_OUT);
- gpio_put(pin_cs, 1);
-
- /* Return. */
- self->vtable = &rp2040_hwspi_vtable;
- self->inst = inst;
- self->pin_cs = pin_cs;
-}
-
-static void rp2040_hwspi_readwritev(implements_spi *_self, const struct bidi_iovec *iov, int iovcnt) {
- struct rp2040_hwspi *self = VCALL_SELF(struct rp2040_hwspi, implements_spi, _self);
- assert(self);
- spi_inst_t *inst = self->inst;
-
- assert(inst);
- assert(iov);
- assert(iovcnt);
-
- gpio_put(self->pin_cs, 0);
- /* TODO: Replace blocking reads+writes with DMA. */
- for (int i = 0; i < iovcnt; i++) {
- if (iov[i].iov_write_src && iov[i].iov_read_dst)
- spi_write_read_blocking(inst, iov[i].iov_write_src, iov[i].iov_read_dst, iov[i].iov_len);
- 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);
- else
- assert(false);
- }
- gpio_put(self->pin_cs, 1);
-}