From 5184668f82240861fe9ad6187027eefb2678aa11 Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Thu, 19 Dec 2024 17:43:12 +0000 Subject: [PATCH] [dif,dma] Update DIF for addressing modes DMA has been modified to offer more flexible address. Update DIF to remove the handshaking configuration and introduce testing of SRC_CONFIG and DST_CONFIG registers and the various addressing modes. Signed-off-by: Adrian Lees --- sw/device/lib/dif/dif_dma.c | 30 +++-- sw/device/lib/dif/dif_dma.h | 35 +++--- sw/device/lib/dif/dif_dma_unittest.cc | 153 +++++++++++++++++++++----- 3 files changed, 161 insertions(+), 57 deletions(-) diff --git a/sw/device/lib/dif/dif_dma.c b/sw/device/lib/dif/dif_dma.c index 5010a25c38f52..bd0602c7de287 100644 --- a/sw/device/lib/dif/dif_dma.c +++ b/sw/device/lib/dif/dif_dma.c @@ -25,24 +25,44 @@ dif_result_t dif_dma_configure(const dif_dma_t *dma, return kDifBadArg; } + // Source address. mmio_region_write32(dma->base_addr, DMA_SRC_ADDR_LO_REG_OFFSET, transaction.source.address & UINT32_MAX); mmio_region_write32(dma->base_addr, DMA_SRC_ADDR_HI_REG_OFFSET, transaction.source.address >> (sizeof(uint32_t) * 8)); + // Destination address. mmio_region_write32(dma->base_addr, DMA_DST_ADDR_LO_REG_OFFSET, transaction.destination.address & UINT32_MAX); mmio_region_write32( dma->base_addr, DMA_DST_ADDR_HI_REG_OFFSET, transaction.destination.address >> (sizeof(uint32_t) * 8)); + // Source configuration. uint32_t reg = 0; + reg = bitfield_bit32_write(reg, DMA_SRC_CONFIG_WRAP_BIT, + transaction.src_config.wrap); + reg = bitfield_bit32_write(reg, DMA_SRC_CONFIG_INCREMENT_BIT, + transaction.src_config.increment); + mmio_region_write32(dma->base_addr, DMA_SRC_CONFIG_REG_OFFSET, reg); + + // Destination configuration. + reg = 0; + reg = bitfield_bit32_write(reg, DMA_DST_CONFIG_WRAP_BIT, + transaction.dst_config.wrap); + reg = bitfield_bit32_write(reg, DMA_DST_CONFIG_INCREMENT_BIT, + transaction.dst_config.increment); + mmio_region_write32(dma->base_addr, DMA_DST_CONFIG_REG_OFFSET, reg); + + // Address Space IDs. + reg = 0; reg = bitfield_field32_write(reg, DMA_ADDR_SPACE_ID_SRC_ASID_FIELD, transaction.source.asid); reg = bitfield_field32_write(reg, DMA_ADDR_SPACE_ID_DST_ASID_FIELD, transaction.destination.asid); mmio_region_write32(dma->base_addr, DMA_ADDR_SPACE_ID_REG_OFFSET, reg); + // Transfer quantities. mmio_region_write32(dma->base_addr, DMA_CHUNK_DATA_SIZE_REG_OFFSET, transaction.chunk_size); mmio_region_write32(dma->base_addr, DMA_TOTAL_DATA_SIZE_REG_OFFSET, @@ -53,8 +73,7 @@ dif_result_t dif_dma_configure(const dif_dma_t *dma, return kDifOk; } -dif_result_t dif_dma_handshake_enable(const dif_dma_t *dma, - dif_dma_handshake_t handshake) { +dif_result_t dif_dma_handshake_enable(const dif_dma_t *dma) { if (dma == NULL) { return kDifBadArg; } @@ -62,13 +81,6 @@ dif_result_t dif_dma_handshake_enable(const dif_dma_t *dma, uint32_t reg = mmio_region_read32(dma->base_addr, DMA_CONTROL_REG_OFFSET); reg = bitfield_bit32_write(reg, DMA_CONTROL_HARDWARE_HANDSHAKE_ENABLE_BIT, true); - reg = bitfield_bit32_write(reg, DMA_CONTROL_FIFO_AUTO_INCREMENT_ENABLE_BIT, - handshake.fifo_auto_increment); - reg = bitfield_bit32_write( - reg, DMA_CONTROL_MEMORY_BUFFER_AUTO_INCREMENT_ENABLE_BIT, - handshake.memory_auto_increment); - reg = bitfield_bit32_write(reg, DMA_CONTROL_DATA_DIRECTION_BIT, - handshake.direction_from_mem_to_fifo); mmio_region_write32(dma->base_addr, DMA_CONTROL_REG_OFFSET, reg); return kDifOk; } diff --git a/sw/device/lib/dif/dif_dma.h b/sw/device/lib/dif/dif_dma.h index 35d667f1fa595..2958492d4b9ea 100644 --- a/sw/device/lib/dif/dif_dma.h +++ b/sw/device/lib/dif/dif_dma.h @@ -63,12 +63,24 @@ typedef struct dif_dma_transaction_address { dif_dma_address_space_id_t asid; } dif_dma_transaction_address_t; +/** + * Addressing configuration. + */ +typedef struct dif_dma_address_config { + /* Address wraps after each chunk, so chunks overlap */ + bool wrap; + /* Increment after each (partial-)word transfer */ + bool increment; +} dif_dma_address_config_t; + /** * Parameters for a DMA Controller transaction. */ typedef struct dif_dma_transaction { dif_dma_transaction_address_t source; dif_dma_transaction_address_t destination; + dif_dma_address_config_t src_config; + dif_dma_address_config_t dst_config; /* Chunk size (in bytes) of the data object to transferred.*/ size_t chunk_size; /* Total size (in bytes) of the data object to transferred.*/ @@ -90,24 +102,6 @@ OT_WARN_UNUSED_RESULT dif_result_t dif_dma_configure(const dif_dma_t *dma, dif_dma_transaction_t transaction); -/** - * Parameters for a handshake mode transaction. - */ -typedef struct dif_dma_handshake { - /* Auto Increments the memory buffer address register by total data size to - * point to the next memory buffer address.*/ - bool memory_auto_increment; - - /* If `true`, reads/writes from/to incremental addresses for FIFO data - * register addresses, otherwise uses the same address for subsequent - * transactions.*/ - bool fifo_auto_increment; - - /* If `true` move data from memory buffer to the LSIO FIFO, otherwise move - * data from the LSIO FIFO to the memory buffer.*/ - bool direction_from_mem_to_fifo; -} dif_dma_handshake_t; - /** * Configures DMA Controller hardware handshake mode. * @@ -117,12 +111,10 @@ typedef struct dif_dma_handshake { * peripherals receiving data e.g. I3C receive buffer. * * @param dma A DMA Controller handle. - * @param handshake Hardware handshake configuration parameters. * @return The result of the operation. */ OT_WARN_UNUSED_RESULT -dif_result_t dif_dma_handshake_enable(const dif_dma_t *dma, - dif_dma_handshake_t handshake); +dif_result_t dif_dma_handshake_enable(const dif_dma_t *dma); /** * Disable DMA Controller hardware handshake mode. @@ -234,6 +226,7 @@ typedef enum dif_dma_status_code { * Bitmask with the `dif_dma_status_code_t` values. */ typedef uint32_t dif_dma_status_t; + /** * Reads the DMA status. * diff --git a/sw/device/lib/dif/dif_dma_unittest.cc b/sw/device/lib/dif/dif_dma_unittest.cc index 2b41714ef867f..d81b6ed544f87 100644 --- a/sw/device/lib/dif/dif_dma_unittest.cc +++ b/sw/device/lib/dif/dif_dma_unittest.cc @@ -46,6 +46,19 @@ TEST_P(ConfigureTest, Success) { EXPECT_WRITE32(DMA_DST_ADDR_HI_REG_OFFSET, transaction.destination.address >> 32); + EXPECT_WRITE32( + DMA_SRC_CONFIG_REG_OFFSET, + { + {DMA_SRC_CONFIG_INCREMENT_BIT, transaction.src_config.increment}, + {DMA_SRC_CONFIG_WRAP_BIT, transaction.src_config.wrap}, + }); + EXPECT_WRITE32( + DMA_DST_CONFIG_REG_OFFSET, + { + {DMA_DST_CONFIG_INCREMENT_BIT, transaction.dst_config.increment}, + {DMA_DST_CONFIG_WRAP_BIT, transaction.dst_config.wrap}, + }); + EXPECT_WRITE32( DMA_ADDR_SPACE_ID_REG_OFFSET, { @@ -75,6 +88,18 @@ INSTANTIATE_TEST_SUITE_P( .address = 0x721F400F, .asid = kDifDmaOpentitanInternalBus, }, + // Regular memory behavior. + .src_config = + { + .wrap = 0, + .increment = 1, + }, + // Typical FIFO behavior. + .dst_config = + { + .wrap = 1, + .increment = 0, + }, .chunk_size = 0x1, .total_size = 0x1, .width = kDifDmaTransWidth1Byte, @@ -91,6 +116,18 @@ INSTANTIATE_TEST_SUITE_P( .address = 0xD0CF2C50, .asid = kDifDmaSoCControlRegisterBus, }, + // Typical FIFO behavior. + .src_config = + { + .wrap = 1, + .increment = 0, + }, + // Regular memory behavior. + .dst_config = + { + .wrap = 0, + .increment = 1, + }, .chunk_size = 0x2, .total_size = 0x2, .width = kDifDmaTransWidth2Bytes, @@ -107,6 +144,18 @@ INSTANTIATE_TEST_SUITE_P( .address = 0x32CD872A12225CCE, .asid = kDifDmaSoCSystemBus, }, + // Regular memory behavior. + .src_config = + { + .wrap = 0, + .increment = 1, + }, + // FIFO occupying a block of addresses. + .dst_config = + { + .wrap = 1, + .increment = 1, + }, .chunk_size = 0x4, .total_size = 0x4, .width = kDifDmaTransWidth4Bytes, @@ -123,10 +172,78 @@ INSTANTIATE_TEST_SUITE_P( .address = 0x9ECFA11919F684D7, .asid = kDifDmaOpentitanInternalBus, }, + // Regular memory behavior. + .src_config = + { + .wrap = 0, + .increment = 1, + }, + // Regular memory behavior. + .dst_config = + { + .wrap = 0, + .increment = 1, + }, .chunk_size = std::numeric_limits::max(), .total_size = std::numeric_limits::max(), .width = kDifDmaTransWidth4Bytes, }, + // Test 4 + { + .source = + { + .address = 0x05BA857F8D9C0838, + .asid = kDifDmaSoCControlRegisterBus, + }, + .destination = + { + .address = 0x32CD872A12225CCE, + .asid = kDifDmaSoCSystemBus, + }, + // Unusual addressing; FIFO-like but not wrapping. + .src_config = + { + .wrap = 0, + .increment = 0, + }, + // Typical FIFO behavior. + .dst_config = + { + .wrap = 1, + .increment = 0, + }, + .chunk_size = 0x4, + .total_size = 0x4, + .width = kDifDmaTransWidth4Bytes, + }, + // Test 5 + { + .source = + { + .address = 0x05BA857F8D9C0838, + .asid = kDifDmaSoCControlRegisterBus, + }, + .destination = + { + .address = 0x32CD872A12225CCE, + .asid = kDifDmaSoCSystemBus, + }, + // Chunk-based firmware-controlled transfer. + .src_config = + { + .wrap = 1, + .increment = 1, + }, + // Unusual addressing; FIFO-like but not wrapping. + .dst_config = + { + .wrap = 0, + .increment = 0, + }, + .chunk_size = 0x4, + .total_size = 0x4, + .width = kDifDmaTransWidth4Bytes, + }, }})); TEST_F(ConfigureTest, BadArg) { @@ -135,28 +252,22 @@ TEST_F(ConfigureTest, BadArg) { } // Handshake tests -class HandshakeTest : public DmaTestInitialized, - public testing::WithParamInterface { -}; +class HandshakeTest : public DmaTestInitialized {}; -TEST_P(HandshakeTest, EnableSuccess) { - dif_dma_handshake_t handshake = GetParam(); - EXPECT_READ32(DMA_CONTROL_REG_OFFSET, 0); +TEST_F(HandshakeTest, EnableSuccess) { + EXPECT_READ32(DMA_CONTROL_REG_OFFSET, + { + {DMA_CONTROL_HARDWARE_HANDSHAKE_ENABLE_BIT, true}, + }); EXPECT_WRITE32(DMA_CONTROL_REG_OFFSET, { - {DMA_CONTROL_DATA_DIRECTION_BIT, - handshake.direction_from_mem_to_fifo}, - {DMA_CONTROL_FIFO_AUTO_INCREMENT_ENABLE_BIT, - handshake.fifo_auto_increment}, - {DMA_CONTROL_MEMORY_BUFFER_AUTO_INCREMENT_ENABLE_BIT, - handshake.memory_auto_increment}, {DMA_CONTROL_HARDWARE_HANDSHAKE_ENABLE_BIT, true}, }); - EXPECT_DIF_OK(dif_dma_handshake_enable(&dma_, handshake)); + EXPECT_DIF_OK(dif_dma_handshake_enable(&dma_)); } -TEST_P(HandshakeTest, DisableSuccess) { +TEST_F(HandshakeTest, DisableSuccess) { EXPECT_READ32(DMA_CONTROL_REG_OFFSET, { {DMA_CONTROL_HARDWARE_HANDSHAKE_ENABLE_BIT, true}, @@ -169,20 +280,8 @@ TEST_P(HandshakeTest, DisableSuccess) { EXPECT_DIF_OK(dif_dma_handshake_disable(&dma_)); } -INSTANTIATE_TEST_SUITE_P(HandshakeTest, HandshakeTest, - testing::ValuesIn(std::vector{{ - {false, false, false}, - {false, false, true}, - {false, true, false}, - {false, true, true}, - {true, false, false}, - {true, true, false}, - {true, true, true}, - }})); - TEST_F(HandshakeTest, EnableBadArg) { - dif_dma_handshake_t handshake; - EXPECT_DIF_BADARG(dif_dma_handshake_enable(nullptr, handshake)); + EXPECT_DIF_BADARG(dif_dma_handshake_enable(nullptr)); } TEST_F(HandshakeTest, DisableBadArg) {