summaryrefslogtreecommitdiffstats
path: root/driver/hdm-dim2/dim2_hal.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/hdm-dim2/dim2_hal.c')
-rw-r--r--driver/hdm-dim2/dim2_hal.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/driver/hdm-dim2/dim2_hal.c b/driver/hdm-dim2/dim2_hal.c
index 022df5c..6f2b6e4 100644
--- a/driver/hdm-dim2/dim2_hal.c
+++ b/driver/hdm-dim2/dim2_hal.c
@@ -135,15 +135,34 @@ static void free_dbr(int offs, int size)
/* -------------------------------------------------------------------------- */
-static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx)
+static void dim2_transfer_madr(u32 val)
{
- dimcb_io_write(&g.dim2->MADR, ctr_addr);
+ dimcb_io_write(&g.dim2->MADR, val);
- /* wait till transfer is completed */
+ /* wait for transfer completion */
while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1)
continue;
dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */
+}
+
+static void dim2_clear_dbr(u16 addr, u16 size)
+{
+ enum { MADR_TB_BIT = 30, MADR_WNR_BIT = 31 };
+
+ u16 const end_addr = addr + size;
+ u32 const cmd = bit_mask(MADR_WNR_BIT) | bit_mask(MADR_TB_BIT);
+
+ dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */
+ dimcb_io_write(&g.dim2->MDAT0, 0);
+
+ for (; addr < end_addr; addr++)
+ dim2_transfer_madr(cmd | addr);
+}
+
+static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx)
+{
+ dim2_transfer_madr(ctr_addr);
return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx);
}
@@ -168,13 +187,7 @@ static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value)
dimcb_io_write(&g.dim2->MDWE2, mask[2]);
dimcb_io_write(&g.dim2->MDWE3, mask[3]);
- dimcb_io_write(&g.dim2->MADR, bit_mask(MADR_WNR_BIT) | ctr_addr);
-
- /* wait till transfer is completed */
- while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1)
- continue;
-
- dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */
+ dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr);
}
static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value)
@@ -793,6 +806,7 @@ u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
sync_init(ch, ch_address / 2, bytes_per_frame);
+ dim2_clear_dbr(ch->dbr_addr, ch->dbr_size);
dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx,
ch->dbr_addr, ch->dbr_size, 0, true);