DMA_CH_CONTEXT *ch;
ch = handle;
+ dmavdbg("DMA ch %d start\n", ch->dma_chan_num);
+
/* Somwhere here run DMA */
ch->task = task;
#define DMA_MC_1B_SET(a, b) (*(char *)(a) = (char)(b))
#define DMA_MC_EV_SET(a, b) (*(char *)(a) = (char)(b << 3))
+#define DMA_NOP (0x18)
/************************************************************************************
* Public Types
DMA_CH7
} DMA_CHANNEL_NUM;
-
typedef struct dma_drvdata dma_drvdata;
typedef struct {
void *SAR;
void *DAR;
void *CCR;
+ void *LOOP2;
void *LOOP1;
void *LOOP0;
void *EVENT_CH;
+ void *finish_1;
+ void *finish_2;
+ int finish_size;
} t_dma_task_priv;
/****************************************************************************
t_dma_task_priv *priv_task = (t_dma_task_priv *) task;
DMA_CH_CONTEXT *ch;
ch = handle;
+ unsigned int tx_num = (task->size / 4) & (~0xFF);
+ unsigned int tx_num_residual = (task->size / 4) & 0xFF;
priv_task->chflags = CCR_M2P_DFLT |
SRC_BURST_SIZE(BS_1) |
DMA_MC_4B_SET(priv_task->SAR, task->src);
DMA_MC_4B_SET(priv_task->DAR, task->dst);
DMA_MC_4B_SET(priv_task->CCR, priv_task->chflags);
- DMA_MC_1B_SET(priv_task->LOOP1, (((task->size / 4 - 1) >> 8) & 0xFF));
- DMA_MC_1B_SET(priv_task->LOOP0, (task->size / 4 - 1) & 0xFF);
+
+ if (tx_num > 0) {
+ DMA_MC_1B_SET(priv_task->LOOP1, (((tx_num - 1) >> 8) & 0xFF));
+ DMA_MC_1B_SET(priv_task->LOOP0, (tx_num - 1) & 0xFF);
+
+ DMA_MC_1B_SET(priv_task->LOOP2, (tx_num_residual - 1) & 0xFF);
+ } else {
+ DMA_MC_1B_SET(priv_task->LOOP1, 0);
+ DMA_MC_1B_SET(priv_task->LOOP0, (tx_num_residual - 1) & 0xFF);
+ }
DMA_MC_EV_SET(priv_task->EVENT_CH, ch->dma_chan_num);
+ if ((tx_num_residual == 0) || (tx_num == 0)) {
+ memcpy(priv_task->finish_1, priv_task->finish_2, priv_task->finish_size);
+ } else {
+ memset(priv_task->finish_1, DMA_NOP, priv_task->finish_size);
+ }
+
arch_clean_dcache((uintptr_t)task->microcode,
(uintptr_t)(task->microcode + priv_task->mc_size));
void *mc_base;
void *loop_offs0;
void *loop_offs1;
+ void *loop_offs2;
task = zalloc(sizeof(t_dma_task_priv));
if (task == NULL) {
return NULL;
}
- task->microcode = zalloc(64);
+ task->microcode = zalloc(128);
if (task->microcode == NULL) {
dmadbg("ERROR: Failed to allocate microcode memory\n");
free(task);
}
priv_task = (t_dma_task_priv *) task;
- priv_task->mc_array_size = 64;
+ priv_task->mc_array_size = 128;
mc_base = task->microcode;
-
+ /* Set src, dst, ctrl registers */
mc_base += DMA_Encode_DMAMOV(mc_base, &(priv_task->SAR), DMA_SAR);
mc_base += DMA_Encode_DMAMOV(mc_base, &(priv_task->DAR), DMA_DAR);
mc_base += DMA_Encode_DMAMOV(mc_base, &(priv_task->CCR), DMA_CCR);
mc_base += DMA_Encode_DMAFLUSHP(mc_base, d_ph_ch);
- /*loop start */
+ /* Basic loop start */
mc_base += DMA_Encode_DMALP(mc_base, LC1, &(priv_task->LOOP1));
loop_offs1 = mc_base;
mc_base += DMA_Encode_DMALP(mc_base, LC0, &(priv_task->LOOP0));
loop_offs0 = mc_base;
- /* 0 - wait for either Sinnle/Busrs requests */
- mc_base += DMA_Encode_DMAWFP(mc_base, 1, d_ph_ch);
+ mc_base += DMA_Encode_DMAWFP(mc_base, 1, d_ph_ch); /* 0 - wait for either Sinnle/Busrs requests */
+
+ mc_base += DMA_Encode_DMALD(mc_base, 0); /* 0 - LD does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMALD(mc_base, 0); /* 0 - LD does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMALD(mc_base, 0); /* 0 - LD does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMALD(mc_base, 0); /* 0 - LD does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMASTP(mc_base, 0, d_ph_ch); /* 0 - STP singles / NOP burst */
+ mc_base += DMA_Encode_DMASTP(mc_base, 2, d_ph_ch); /* 2 - NOP singles / STP burst */
+
+ mc_base += DMA_Encode_DMAFLUSHP(mc_base, d_ph_ch);
+
+ mc_base += DMA_Encode_DMALPEND(mc_base, LC0_END, mc_base - loop_offs0);
+ mc_base += DMA_Encode_DMALPEND(mc_base, LC1_END, mc_base - loop_offs1);
+ /*Basic loop end */
- /* 0 - LD does not depend on burst L/S settings */
- mc_base += DMA_Encode_DMALD(mc_base, 0);
- mc_base += DMA_Encode_DMALD(mc_base, 0);
- mc_base += DMA_Encode_DMALD(mc_base, 0);
- mc_base += DMA_Encode_DMALD(mc_base, 0);
+ /* Finish here, if only basic loop used */
+ priv_task->finish_1 = mc_base;
+ mc_base += DMA_Encode_DMAWMB(mc_base);
+ mc_base += DMA_Encode_DMASEV(mc_base, &(priv_task->EVENT_CH));
+ mc_base += DMA_Encode_DMAEND(mc_base);
+ priv_task->finish_size = mc_base - priv_task->finish_1;
+
+ /* Additional loop start */
+ mc_base += DMA_Encode_DMALP(mc_base, LC0, &(priv_task->LOOP2));
+ loop_offs2 = mc_base;
- /* 0 - STP singles / NOP burst */
- mc_base += DMA_Encode_DMASTP(mc_base, 0, d_ph_ch);
+ mc_base += DMA_Encode_DMAWFP(mc_base, 1, d_ph_ch); /* 0 - wait for either Sinnle/Busrs requests */
- /* 2 - NOP singles / STP burst */
- mc_base += DMA_Encode_DMASTP(mc_base, 2, d_ph_ch);
+ mc_base += DMA_Encode_DMALD(mc_base, 0); /* 0 - LD does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMALD(mc_base, 0); /* 0 - LD does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMALD(mc_base, 0); /* 0 - LD does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMALD(mc_base, 0); /* 0 - LD does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMASTP(mc_base, 0, d_ph_ch); /* 0 - STP singles / NOP burst */
+ mc_base += DMA_Encode_DMASTP(mc_base, 2, d_ph_ch); /* 2 - NOP singles / STP burst */
mc_base += DMA_Encode_DMAFLUSHP(mc_base, d_ph_ch);
+ mc_base += DMA_Encode_DMALPEND(mc_base, LC0_END, mc_base - loop_offs2);
/*loop end */
- mc_base += DMA_Encode_DMALPEND(mc_base, LC0_END, mc_base - loop_offs0);
- mc_base += DMA_Encode_DMALPEND(mc_base, LC1_END, mc_base - loop_offs1);
+ priv_task->finish_2 = mc_base;
mc_base += DMA_Encode_DMAWMB(mc_base);
mc_base += DMA_Encode_DMASEV(mc_base, &(priv_task->EVENT_CH));
mc_base += DMA_Encode_DMAEND(mc_base);
void *SAR;
void *DAR;
void *CCR;
+ void *LOOP2;
void *LOOP1;
void *LOOP0;
void *EVENT_CH;
+ void *finish_1;
+ void *finish_2;
+ int finish_size;
} t_dma_task_priv;
/****************************************************************************
t_dma_task_priv *priv_task = (t_dma_task_priv *) task;
DMA_CH_CONTEXT *ch;
ch = handle;
+ unsigned int rx_num = (task->size / 4) & (~0xFF);
+ unsigned int rx_num_residual = (task->size / 4) & 0xFF;
priv_task->chflags = CCR_P2M_DFLT |
SRC_BURST_SIZE(BS_4) |
DMA_MC_4B_SET(priv_task->SAR, task->src);
DMA_MC_4B_SET(priv_task->DAR, task->dst);
DMA_MC_4B_SET(priv_task->CCR, priv_task->chflags);
- DMA_MC_1B_SET(priv_task->LOOP1, (((task->size / 4 - 1) >> 8) & 0xFF));
- DMA_MC_1B_SET(priv_task->LOOP0, (task->size / 4 - 1) & 0xFF);
+
+ if (rx_num > 0) {
+ DMA_MC_1B_SET(priv_task->LOOP1, (((rx_num - 1) >> 8) & 0xFF));
+ DMA_MC_1B_SET(priv_task->LOOP0, (rx_num - 1) & 0xFF);
+
+ DMA_MC_1B_SET(priv_task->LOOP2, (rx_num_residual - 1) & 0xFF);
+ } else {
+ DMA_MC_1B_SET(priv_task->LOOP1, 0);
+ DMA_MC_1B_SET(priv_task->LOOP0, (rx_num_residual - 1) & 0xFF);
+ }
DMA_MC_EV_SET(priv_task->EVENT_CH, ch->dma_chan_num);
+ if ((rx_num_residual == 0) || (rx_num == 0)) {
+ memcpy(priv_task->finish_1, priv_task->finish_2, priv_task->finish_size);
+ } else {
+ memset(priv_task->finish_1, DMA_NOP, priv_task->finish_size);
+ }
+
arch_clean_dcache((uintptr_t)task->microcode,
(uintptr_t)(task->microcode + priv_task->mc_size));
void *mc_base;
void *loop_offs0;
void *loop_offs1;
+ void *loop_offs2;
task = zalloc(sizeof(t_dma_task_priv));
if (task == NULL) {
return NULL;
}
- task->microcode = zalloc(64);
+ task->microcode = zalloc(128);
if (task->microcode == NULL) {
dmadbg("ERROR: Failed to allocate microcode memory\n");
free(task);
}
priv_task = (t_dma_task_priv *) task;
- priv_task->mc_array_size = 64;
+ priv_task->mc_array_size = 128;
mc_base = task->microcode;
-
+ /* Set src, dst, ctrl registers */
mc_base += DMA_Encode_DMAMOV(mc_base, &(priv_task->SAR), DMA_SAR);
mc_base += DMA_Encode_DMAMOV(mc_base, &(priv_task->DAR), DMA_DAR);
mc_base += DMA_Encode_DMAMOV(mc_base, &(priv_task->CCR), DMA_CCR);
mc_base += DMA_Encode_DMAFLUSHP(mc_base, s_ph_ch);
- /*loop start */
+ /*Basic loop start */
mc_base += DMA_Encode_DMALP(mc_base, LC1, &(priv_task->LOOP1));
loop_offs1 = mc_base;
mc_base += DMA_Encode_DMALP(mc_base, LC0, &(priv_task->LOOP0));
loop_offs0 = mc_base;
- /* 0 - wait for either Single/Busrst requests */
- mc_base += DMA_Encode_DMAWFP(mc_base, 1, s_ph_ch);
+ mc_base += DMA_Encode_DMAWFP(mc_base, 1, s_ph_ch); /* 0 - wait for either Single/Busrst requests */
- /* 0 - LDP singles / NOP burst */
- mc_base += DMA_Encode_DMALDP(mc_base, 0, s_ph_ch);
+ mc_base += DMA_Encode_DMALDP(mc_base, 0, s_ph_ch); /* 0 - LDP singles / NOP burst */
+ mc_base += DMA_Encode_DMALDP(mc_base, 2, s_ph_ch); /* 2 - NOP singles / STP burst */
+ mc_base += DMA_Encode_DMAST(mc_base, 0); /* 0 - ST does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMAST(mc_base, 0); /* 0 - ST does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMAST(mc_base, 0); /* 0 - ST does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMAST(mc_base, 0); /* 0 - ST does not depend on burst L/S settings */
- /* 2 - NOP singles / STP burst */
- mc_base += DMA_Encode_DMALDP(mc_base, 2, s_ph_ch);
+ mc_base += DMA_Encode_DMAFLUSHP(mc_base, s_ph_ch);
- /* 0 - ST does not depend on burst L/S settings */
- mc_base += DMA_Encode_DMAST(mc_base, 0);
- mc_base += DMA_Encode_DMAST(mc_base, 0);
- mc_base += DMA_Encode_DMAST(mc_base, 0);
- mc_base += DMA_Encode_DMAST(mc_base, 0);
+ mc_base += DMA_Encode_DMALPEND(mc_base, LC0_END, mc_base - loop_offs0);
+ mc_base += DMA_Encode_DMALPEND(mc_base, LC1_END, mc_base - loop_offs1);
+ /*Basic loop end */
+
+ /* Finish here, if only basic loop used */
+ priv_task->finish_1 = mc_base;
+ mc_base += DMA_Encode_DMAWMB(mc_base);
+ mc_base += DMA_Encode_DMASEV(mc_base, &(priv_task->EVENT_CH));
+ mc_base += DMA_Encode_DMAEND(mc_base);
+ priv_task->finish_size = mc_base - priv_task->finish_1;
+
+ /* Additional loop start */
+ mc_base += DMA_Encode_DMALP(mc_base, LC0, &(priv_task->LOOP2));
+ loop_offs2 = mc_base;
+
+ mc_base += DMA_Encode_DMAWFP(mc_base, 1, s_ph_ch); /* 0 - wait for either Sinnle/Busrs requests */
+
+ mc_base += DMA_Encode_DMALDP(mc_base, 0, s_ph_ch); /* 0 - LDP singles / NOP burst */
+ mc_base += DMA_Encode_DMALDP(mc_base, 2, s_ph_ch); /* 2 - NOP singles / STP burst */
+ mc_base += DMA_Encode_DMAST(mc_base, 0); /* 0 - ST does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMAST(mc_base, 0); /* 0 - ST does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMAST(mc_base, 0); /* 0 - ST does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMAST(mc_base, 0); /* 0 - ST does not depend on burst L/S settings */
mc_base += DMA_Encode_DMAFLUSHP(mc_base, s_ph_ch);
+ mc_base += DMA_Encode_DMALPEND(mc_base, LC0_END, mc_base - loop_offs2);
/*loop end */
- mc_base += DMA_Encode_DMALPEND(mc_base, LC0_END, mc_base - loop_offs0);
- mc_base += DMA_Encode_DMALPEND(mc_base, LC1_END, mc_base - loop_offs1);
+ priv_task->finish_2 = mc_base;
+ mc_base += DMA_Encode_DMAWMB(mc_base);
mc_base += DMA_Encode_DMASEV(mc_base, &(priv_task->EVENT_CH));
mc_base += DMA_Encode_DMAEND(mc_base);