diff options
author | Mark Rawling <mwr@google.com> | 2021-10-04 13:10:48 -0700 |
---|---|---|
committer | Andrew Evans <andrewevans@google.com> | 2022-04-19 10:16:03 -0700 |
commit | 01cfc37c8acbba6eb05accef0fa6bbb73616b674 (patch) | |
tree | fdbc30553cef1a84edc4d4b9aa2070f76353a04c | |
parent | 8cd026832d2f4d8f4f94a5e2772f2b01cce57bd5 (diff) | |
download | nanohub-01cfc37c8acbba6eb05accef0fa6bbb73616b674.tar.gz |
DMA support for Nanohub
- ensures burst mode operation for fast, continuous clock
- adjusts the timeout padding to maintain similar timing to the MCU
- relies on the new exponential back-off flow control for overall
reliability
DMA is critically dependent on burst mode operation, and is essentially
unusable without it. Burst mode ensures a solid clock that doesn't
stutter under system load or governor control.
DMA has advantages and disadvantages:
- continuous clock in burst mode versus 64 bytes on/64 bytes off in
non-dma mode
- less cpu load and interrupt driven without the spinlocks used in
non-DMA mode
- slower transaction setup and hold times which limits performance,
we will improve this further
- non-burst mode degrades markedly with mif qos so we won't be using it
The timing is set to approximate the current transaciton timing. It
will be tuned and customized for optimal timing with DMA in follow up
CLs.
See go/rh-nanohub-mcu-architecture
Test: manual, with induced retries and continuous stress tests
Bug: 185406845
Bug: 169772504
Bug: 200616501
Change-Id: I7f90f250f9c902ee473606ee2ec2383b409ec874
-rw-r--r-- | spi.c | 10 |
1 files changed, 8 insertions, 2 deletions
@@ -25,6 +25,9 @@ #define SPI_TIMEOUT 65535 #define SPI_MIN_DMA 48 #define SPI_MAX_SPEED_HZ 10000000 +#define SPI_BITS_PER_WORD 8 +#define DMA_BURST_WIDTH 4 +#define DMA_PAD 3 struct nanohub_spi_data { struct nanohub_data data; @@ -246,6 +249,7 @@ int nanohub_spi_write(void *data, uint8_t *tx, int length, int timeout) .rx_buf = comms->rx_buffer, .cs_change = 1, }; + xfer.len = (xfer.len + DMA_PAD) & ~DMA_PAD; spi_data->rx_offset = max_len; spi_data->rx_length = max_len + timeout; memcpy(comms->tx_buffer, tx, length); @@ -315,6 +319,7 @@ int nanohub_spi_read(void *data, uint8_t *rx, int max_length, int timeout) } } + xfer.len = (xfer.len + DMA_PAD) & ~DMA_PAD; if (xfer.len != 1 && xfer.len < SPI_MIN_DMA) xfer.len = SPI_MIN_DMA; memset(comms->tx_buffer, 0xFF, xfer.len); @@ -380,7 +385,7 @@ static int nanohub_spi_open(void *data) spi_bus_lock(spi_data->device->master); spi_data->device->max_speed_hz = spi_data->data.max_speed_hz; spi_data->device->mode = SPI_MODE_0; - spi_data->device->bits_per_word = 8; + spi_data->device->bits_per_word = SPI_BITS_PER_WORD; ret = spi_setup(spi_data->device); if (!ret) { udelay(40); @@ -407,7 +412,7 @@ void nanohub_spi_comms_init(struct nanohub_spi_data *spi_data) sizeof(struct nanohub_packet_crc); comms->seq = 1; - comms->timeout_write = 544; + comms->timeout_write = 760; comms->timeout_ack = 272; comms->timeout_reply = 512; comms->open = nanohub_spi_open; @@ -418,6 +423,7 @@ void nanohub_spi_comms_init(struct nanohub_spi_data *spi_data) max_len += comms->timeout_write; max_len = max(max_len, comms->timeout_ack); max_len = max(max_len, comms->timeout_reply); + max_len = (max_len + DMA_PAD) & ~DMA_PAD; comms->tx_buffer = kmalloc(max_len, GFP_KERNEL | GFP_DMA); comms->rx_buffer = kmalloc(max_len, GFP_KERNEL | GFP_DMA); |