Skip to content

Commit

Permalink
[dif,dma] Update DIF for addressing modes
Browse files Browse the repository at this point in the history
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 <a.lees@lowrisc.org>
  • Loading branch information
alees24 authored and andreaskurth committed Dec 23, 2024
1 parent fa49bd9 commit 5184668
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 57 deletions.
30 changes: 21 additions & 9 deletions sw/device/lib/dif/dif_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -53,22 +73,14 @@ 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;
}

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;
}
Expand Down
35 changes: 14 additions & 21 deletions sw/device/lib/dif/dif_dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.*/
Expand All @@ -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.
*
Expand All @@ -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.
Expand Down Expand Up @@ -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.
*
Expand Down
153 changes: 126 additions & 27 deletions sw/device/lib/dif/dif_dma_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
{
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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<uint32_t>::max(),
.total_size = std::numeric_limits<uint32_t>::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) {
Expand All @@ -135,28 +252,22 @@ TEST_F(ConfigureTest, BadArg) {
}

// Handshake tests
class HandshakeTest : public DmaTestInitialized,
public testing::WithParamInterface<dif_dma_handshake_t> {
};
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},
Expand All @@ -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<dif_dma_handshake_t>{{
{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) {
Expand Down

0 comments on commit 5184668

Please sign in to comment.