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