This DMA code initally is intended to be used with I2S driver.
Can be also used with common memory transfers, and other IPs.
Change-Id: If2a30e00a1f2ec7f5d410d11a8b4a3a59814ecf3
Signed-off-by: Ivan <ivan.galkin@samsung.com>
Signed-off-by: Bongryul Lee <bongryul.lee@samsung.com>
Signed-off-by: Junhwan Park <junhwan.park@samsung.com>
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+#ifndef __ARCH_ARM_INCLUDE_S5J_DMA_H
+#define __ARCH_ARM_INCLUDE_S5J_DMA_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+#define s5j_dmasetup(a, b) if((b)->setup) (b)->setup(a, b);
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+typedef enum {
+ DMA_UART0_RX = (0),
+ DMA_UART0_TX = (1),
+ DMA_UART1_RX = (2),
+ DMA_UART1_TX = (3),
+ DMA_UART2_RX = (4),
+ DMA_UART2_TX = (5),
+ DMA_UART3_RX = (6),
+ DMA_UART3_TX = (7),
+ DMA_HSI2C0_RX = (8),
+ DMA_HSI2C0_TX = (9),
+ DMA_HSI2C1_RX = (10),
+ DMA_HSI2C1_TX = (11),
+ DMA_HSI2C2_RX = (12),
+ DMA_HSI2C2_TX = (13),
+ DMA_HSI2C3_RX = (14),
+ DMA_HSI2C3_TX = (15),
+ DMA_SPI0_RX = (16),
+ DMA_SPI0_TX = (17),
+ DMA_SPI1_RX = (18),
+ DMA_SPI1_TX = (19),
+ DMA_SPI2_RX = (20),
+ DMA_SPI2_TX = (21),
+ DMA_SPI3_RX = (22),
+ DMA_SPI3_TX = (23),
+ DMA_I2S_RX = (24),
+ DMA_I2S_TX = (25),
+ DMA_I2S_TX_S = (26),
+ DMA_UART_Debug_RX = (28),
+ DMA_UART_Debug_TX = (29),
+ DMA_PWM0 = (30),
+ DMA_PWM1 = (31),
+} DMA_REQ_MAP;
+
+typedef FAR void *DMA_HANDLE;
+typedef struct dma_task dma_task;
+
+typedef void (*dma_callback_t)(DMA_HANDLE handle, void *arg, int result);
+typedef int (*dma_setup_t)(DMA_HANDLE handle, dma_task *task);
+
+struct dma_task {
+ void *src;
+ void *dst;
+ u32 size;
+ void *microcode;
+
+ dma_setup_t setup;
+
+ dma_callback_t callback;
+ void *arg;
+};
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+DMA_HANDLE s5j_dma_alloc(char *name);
+DMA_HANDLE s5j_dmachannel(uint8_t dmacno, char *name);
+void s5j_dmafree(DMA_HANDLE handle);
+
+dma_task *dma_task_m2m_sb_4B_x256_alloc(void);
+dma_task *dma_task_m2p_sb_4B_x256_alloc(DMA_REQ_MAP d_ph_ch);
+dma_task *dma_task_p2m_sb_4B_x256_alloc(DMA_REQ_MAP d_ph_ch);
+dma_task *dma_task_m2mp_sb_4B_x256_alloc(void);
+dma_task *dma_task_mp2m_sb_4B_x256_alloc(void);
+
+int s5j_dmatask_free(dma_task *task);
+
+int s5j_dmastart(DMA_HANDLE handle, dma_task *task);
+dma_task *s5j_dmastop(DMA_HANDLE handle);
+
+void dma_clean_dcache(void *start, void *end);
+void dma_invalidate_dcache(void *start, void *end);
+
+#endif
bool
default n
select S5J_HAVE_ADC
+ select S5J_HAVE_DMA
select S5J_HAVE_I2C
select S5J_HAVE_I2S
select S5J_HAVE_MCT
bool
default n
+config S5J_HAVE_DMA
+ bool
+ default n
+
config S5J_HAVE_I2C
bool
default n
S5J has 12-bits ADC with 4 channels. Say Y here, if you want
to use it.
+config S5J_DMA
+ bool "DMA"
+ default n
+ depends on S5J_HAVE_DMA
+
config S5J_I2C
bool "I2C"
default n
CHIP_CSRCS += s5j_adc.c
endif
+ifeq ($(CONFIG_S5J_DMA),y)
+CHIP_CSRCS += s5j_dma.c
+CHIP_CSRCS += s5j_dma_m2m_sb_4B_x256.c
+CHIP_CSRCS += s5j_dma_m2p_sb_4B_x256.c
+CHIP_CSRCS += s5j_dma_p2m_sb_4B_x256.c
+endif
+
ifeq ($(CONFIG_S5J_I2C),y)
CHIP_CSRCS += s5j_i2c.c
endif
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+
+#include <tinyara/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <assert.h>
+#include <queue.h>
+#include <debug.h>
+
+#include <arch/board/board.h>
+
+#include <tinyara/irq.h>
+#include <tinyara/arch.h>
+#include <tinyara/kmalloc.h>
+#include <tinyara/wdog.h>
+#include <tinyara/wqueue.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+#include "cache.h"
+
+#include "chip.h"
+#include "s5j_dma.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+int pdma_irq_handler(int irq, FAR void *context, FAR void *arg);
+
+static struct dma_drvdata dma_dev[] = {
+ [0] = {
+ .name = "pdma",
+ .isr_num = IRQ_PDMA_U1, /* IRQ_PDMA, */
+ .isr_handler = pdma_irq_handler,
+ .base = (void *)S5J_PDMA_BASE,
+ },
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static u32 dma_get_intstatus(struct dma_drvdata *dma)
+{
+ return getreg32(dma->base + (u32)(DMAC_INTMIS));
+}
+
+static void dma_enable_ch_interrupt(struct dma_drvdata *dma,
+ DMA_CHANNEL_NUM ch_num)
+{
+ volatile u32 inten_reg;
+ inten_reg = getreg32(dma->base + (u32)(DMAC_INTEN));
+ putreg32((inten_reg | (1 << ch_num)), (dma->base + (u32) DMAC_INTEN));
+}
+
+static void dma_disable_ch_interrupt(struct dma_drvdata *dma,
+ DMA_CHANNEL_NUM ch_num)
+{
+ volatile u32 inten_reg;
+ inten_reg = getreg32(dma->base + (u32)(DMAC_INTEN));
+ putreg32((inten_reg & ~(1 << ch_num)), (dma->base + (u32) DMAC_INTEN));
+}
+
+static u32 dma_clear_ch_interrupt(struct dma_drvdata *dma,
+ DMA_CHANNEL_NUM ch_num)
+{
+
+ volatile u32 reg = getreg32(dma->base + (u32)(DMAC_INTCLR));
+ putreg32((reg | (1 << ch_num)), (dma->base + (u32) DMAC_INTCLR));
+ return getreg32(dma->base + (u32)(DMAC_INTCLR));
+}
+
+static void dma_ch_kill(DMA_CH_CONTEXT *dma_ch)
+{
+ struct dma_drvdata *dma = dma_ch->dma;
+ int debug_inst0;
+
+ /* Debug status busy? */
+ while ((getreg32(dma->base + DMAC_DBG_STATUS) & 0x1));
+
+ debug_inst0 = (0 << 24) | ((0x01) << 16) |
+ (dma_ch->dma_chan_num << 8) | (1 << 0);
+
+ putreg32(debug_inst0, dma->base + (u32) DMAC_DBG_INTST0);
+ putreg32(0, dma->base + DMAC_DBG_CMD);
+}
+
+int pdma_irq_handler(int irq, FAR void *context, FAR void *arg)
+{
+
+ struct dma_drvdata *dma = (struct dma_drvdata *)arg;
+ u32 intstatus;
+ int i;
+ volatile u32 reg;
+
+ intstatus = dma_get_intstatus(dma);
+
+ for (i = 0; i < dma->max_ch_num; i++) {
+ if ((intstatus & (1 << i)) && (dma->dma_ch[i].task->callback)) {
+ dma->dma_ch[i].task->callback(&dma->dma_ch[i],
+ dma->dma_ch[i].task->arg, 0);
+ dma_clear_ch_interrupt(dma, i);
+ dma_disable_ch_interrupt(dma, i);
+ }
+ }
+
+ /* Check faults here */
+ reg = getreg32(dma->base + (u32)(DMAC_FSRC));
+ if (reg) {
+ for (i = 0; i < dma->max_ch_num; i++) {
+ if (reg & (1 << i)) {
+ dmalldbg("\nChannel %d failt FTRD = 0x%x CH_FTR = 0x%x \n",
+ i, getreg32(dma->base + (u32)(DMAC_FTRD)),
+ getreg32(dma->base + (u32)(DMAC_CH_FTR(i))));
+
+ dmalldbg("- CSR 0x%x, CPC 0x%x, SAR 0x%x, DAR 0x%x,\
+ CCR 0x%x, LC0 0x%x, LC1 0x%x\n",
+ getreg32(dma->base + (u32)(DMAC_CH_CSR(i))),
+ getreg32(dma->base + (u32)(DMAC_CH_CPC(i))),
+ getreg32(dma->base + (u32)(DMAC_CH_SAR(i))),
+ getreg32(dma->base + (u32)(DMAC_CH_DAR(i))),
+ getreg32(dma->base + (u32)(DMAC_CH_CCR(i))),
+ getreg32(dma->base + (u32)(DMAC_CH_LC0(i))),
+ getreg32(dma->base + (u32)(DMAC_CH_LC1(i))));
+
+ dmalldbg("- INTEN 0x%x, RIS 0x%x, INTMIS 0x%x,\
+ FSRD 0x%x, FSRC 0x%x, FTRD 0x%x \n",
+ getreg32(dma->base + (u32)(DMAC_INTEN)),
+ getreg32(dma->base + (u32)(DMAC_INT_EVENT_RIS)),
+ getreg32(dma->base + (u32)(DMAC_INTMIS)),
+ getreg32(dma->base + (u32)(DMAC_FSRD)),
+ getreg32(dma->base + (u32)(DMAC_FSRC)),
+ getreg32(dma->base + (u32)(DMAC_FTRD)));
+
+ dma_ch_kill(&dma->dma_ch[i]);
+ dma_disable_ch_interrupt(dma, i);
+ if (dma->dma_ch[i].task->callback) {
+ dma->dma_ch[i].task->callback(&dma->dma_ch[i],
+ dma->dma_ch[i].task->arg, -1);
+ }
+
+ }
+ }
+ }
+ return 0;
+}
+
+static struct dma_drvdata *get_dma_drvdata(char *name)
+{
+ int i;
+
+ i = sizeof(dma_dev) / sizeof(struct dma_drvdata);
+
+ while (i--)
+ if (strcmp(name, dma_dev[i].name) == 0) {
+ return &dma_dev[i];
+ }
+ return NULL;
+}
+
+static void dma_set_max_params(struct dma_drvdata *dma)
+{
+ volatile u32 reg_val;
+
+ reg_val = getreg32(dma->base + (u32)(DMAC_CR0));
+ dma->max_ch_num = ((reg_val >> 4) & 0x7) + 1;
+
+ reg_val = getreg32(dma->base + (u32)(DMAC_CRD));
+ dma->max_burst_size = ((reg_val) & 0x7) + 1;
+
+ reg_val = getreg32(dma->base + (u32)(DMAC_CRD));
+ dma->max_burst_len = ((reg_val >> 20) & 0x1FF) + 1;
+}
+
+static void dma_init(struct dma_drvdata *dma)
+{
+ int i;
+ /* INIT SOMETHING HERE before everything starts */
+ dma_set_max_params(dma);
+ irq_attach(dma->isr_num, dma->isr_handler, dma);
+ up_enable_irq(dma->isr_num);
+
+ for (i = 0; i < 8; i++) {
+ dma->dma_ch[i].dma = dma;
+ dma->dma_ch[i].dma_chan_num = i;
+ dma->dma_ch[i].channel_assigned = 0;
+ }
+
+ dmavdbg("DMA %s is configured\n", dma->name);
+}
+
+static void dma_ch_exec(DMA_CH_CONTEXT *dma_ch)
+{
+ struct dma_drvdata *dma = dma_ch->dma;
+ int secure_status;
+ int debug_inst0;
+
+ while ((getreg32(dma->base + DMAC_DBG_STATUS) & 0x1)) ; /* Debug status busy? */
+
+ secure_status = ((getreg32(dma->base + DMAC_CR0) >> 2) & 0x1);
+ debug_inst0 = (dma_ch->dma_chan_num << 24) |
+ ((0xA0 | secure_status << 1) << 16) |
+ (dma_ch->dma_chan_num << 8) |
+ (0 << 0);
+
+ putreg32(debug_inst0, dma->base + (u32) DMAC_DBG_INTST0);
+ putreg32((int)(dma_ch->task->microcode), dma->base + DMAC_DBG_INTST1);
+ putreg32(0, dma->base + DMAC_DBG_CMD);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: s5j_dma_alloc
+ *
+ * Description:
+ * Allocate first avaliable DMA channel in DMA controller
+ *
+ * Input Parameters:
+ * name - Name of DMA controller
+ *
+ * Returned Value:
+ * allocted DMA channel handler, or NULL;
+ *
+ ****************************************************************************/
+DMA_HANDLE s5j_dma_alloc(char *name)
+{
+ int i;
+ struct dma_drvdata *dma;
+
+ dma = get_dma_drvdata(name);
+
+ if (dma == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < dma->max_ch_num; i++) {
+ if (dma->dma_ch[i].channel_assigned == 0) {
+ dma->dma_ch[i].channel_assigned = 1;
+ return (DMA_HANDLE) & dma->dma_ch[i];
+ }
+ }
+ return NULL;
+}
+
+/****************************************************************************
+ * Name: s5j_dmachannel
+ *
+ * Description:
+ * Allocate specified DMA channel in DMA controller
+ *
+ * Input Parameters:
+ * dmacno - DMA channel number
+ * name - Name of DMA controller
+ *
+ * Returned Value:
+ * allocted DMA channel handler, or NULL;
+ *
+ ****************************************************************************/
+DMA_HANDLE s5j_dmachannel(uint8_t dmacno, char *name)
+{
+ struct dma_drvdata *dma;
+
+ dma = get_dma_drvdata(name);
+
+ if (dma == NULL) {
+ return NULL;
+ }
+
+ if (dmacno >= dma->max_ch_num) {
+ return NULL;
+ }
+
+ if (dma->dma_ch[dmacno].channel_assigned != 0) {
+ return NULL;
+ }
+
+ dma->dma_ch[dmacno].channel_assigned = 1;
+ return (DMA_HANDLE) & dma->dma_ch[dmacno];
+}
+
+/****************************************************************************
+ * Name: s5j_dmafree
+ *
+ * Description:
+ * Release Allocated DMA channel
+ *
+ * Input Parameters:
+ * handle - DMA handler
+ *
+ * Returned Value:
+ * none
+ *
+ ****************************************************************************/
+void s5j_dmafree(DMA_HANDLE handle)
+{
+ DMA_CH_CONTEXT *ch;
+ ch = (DMA_CH_CONTEXT *) handle;
+ ch->channel_assigned = 0;
+ ch->task = NULL;
+ return;
+}
+
+/****************************************************************************
+ * Name: s5j_dmastart
+ *
+ * Description:
+ * Start DMA operation
+ *
+ * Input Parameters:
+ * handle - DMA handler
+ * task - DMA task structure with microcode
+ *
+ * Returned Value:
+ * OK
+ *
+ ****************************************************************************/
+int s5j_dmastart(DMA_HANDLE handle, dma_task *task)
+{
+ DMA_CH_CONTEXT *ch;
+ ch = handle;
+
+ /* Somwhere here run DMA */
+ ch->task = task;
+
+ /* FIXME Here I should put task in DMA queue and start DMA */
+ if (ch->task->callback) {
+ dma_enable_ch_interrupt(ch->dma, ch->dma_chan_num);
+ }
+ dma_ch_exec(ch);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: s5j_dmastop
+ *
+ * Description:
+ * Stop DMA operation
+ *
+ * Input Parameters:
+ * handle - DMA handler
+ *
+ * Returned Value:
+ * task structure, which was in prosess.
+ *
+ ****************************************************************************/
+dma_task *s5j_dmastop(DMA_HANDLE handle)
+{
+ DMA_CH_CONTEXT *ch;
+ dma_task *task;
+
+ ch = handle;
+
+ dma_ch_kill(ch);
+ dma_disable_ch_interrupt(ch->dma, ch->dma_chan_num);
+
+ task = ch->task;
+ ch->task = NULL;
+
+ return task;
+}
+
+/****************************************************************************
+ * Name: s5j_dmatask_free
+ *
+ * Description:
+ * Free DMA task structure and microcode.
+ *
+ * Input Parameters:
+ * task srtucture to free
+ *
+ * Returned Value:
+ * OK
+ *
+ ****************************************************************************/
+int s5j_dmatask_free(dma_task *task)
+{
+ free(task->microcode);
+ free(task);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: up_dmainitialize
+ *
+ * Description:
+ * Initialize the DMA subsystem
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void weak_function up_dmainitialize(void)
+{
+ struct dma_drvdata *dma;
+ dmavdbg("Initialize PDMA 0\n");
+ dma = get_dma_drvdata("pdma");
+
+ if (dma != NULL) {
+ dma_init(dma);
+ } else {
+ dmavdbg("There is NO PDMA 0\n");
+ }
+}
+
+/****************************************************************************
+ * Name: dma_clean_dcache
+ *
+ * Description:
+ * User application clean cache, used with data before transfer;
+ *
+ * Input Parameters:
+ * start - pointer on first byte to clean
+ * end - pointer on last byte to clean
+ *
+ * Returned Value:
+ * none
+ *
+ ****************************************************************************/
+void dma_clean_dcache(void *start, void *end)
+{
+ arch_clean_dcache((uintptr_t) start, (uintptr_t) end);
+}
+
+/****************************************************************************
+ * Name: dma_invalidate_dcache
+ *
+ * Description:
+ * User application invalidate cache, used with data before transfer;
+ *
+ * Input Parameters:
+ * start - pointer on first byte to clean
+ * end - pointer on last byte to clean
+ *
+ * Returned Value:
+ * none
+ *
+ ****************************************************************************/
+void dma_invalidate_dcache(void *start, void *end)
+{
+ arch_invalidate_dcache((uintptr_t) start, (uintptr_t) end);
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_S5J_PDMA_H
+#define __ARCH_ARM_SRC_S5J_PDMA_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <tinyara/config.h>
+#include <tinyara/compiler.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <debug.h>
+
+#include <tinyara/irq.h>
+
+#include <arch/s5j/dma.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DMAC_MAX_CH 8
+
+#define DMAC_DSR (0x000)
+#define DMAC_DPC (0x004)
+
+#define DMAC_INTEN (0x020)
+#define DMAC_INT_EVENT_RIS (0x024)
+#define DMAC_INTMIS (0x028)
+#define DMAC_INTCLR (0x02C)
+#define DMAC_FSRD (0x030)
+#define DMAC_FSRC (0x034)
+#define DMAC_FTRD (0x038)
+
+#define DMAC_CH_FTR(n) 0x040 + 0x04*(n)
+#define DMAC_CH_CSR(n) (u32)(0x100 + 0x08*(n))
+#define DMAC_CH_CPC(n) 0x104 + 0x08*(n)
+#define DMAC_CH_SAR(n) 0x400 + 0x20*(n)
+#define DMAC_CH_DAR(n) 0x404 + 0x20*(n)
+#define DMAC_CH_CCR(n) 0x408 + 0x20*(n)
+#define DMAC_CH_LC0(n) 0x40C + 0x20*(n)
+#define DMAC_CH_LC1(n) 0x410 + 0x20*(n)
+
+#define DMAC_DBG_STATUS 0xD00
+#define DMAC_DBG_CMD 0xD04
+#define DMAC_DBG_INTST0 0xD08
+#define DMAC_DBG_INTST1 0xD0C
+
+#define DMAC_CR0 0xE00
+#define DMAC_CR1 0xE04
+#define DMAC_CR2 0xE08
+#define DMAC_CR3 0xE0C
+#define DMAC_CR4 0xE10
+#define DMAC_CRD 0xE14
+#define DMAC_WD 0xE80
+
+#define DMA_BYTE(inst) (u8)((inst) & 0xFF)
+#define DMA_LOOP_MAX 256
+
+/* CCR BITFIELDS */
+
+#define NOSWAP (0)
+#define ENDIAN_SWAP_SIZE_MASK (7 << 28)
+#define ENDIAN_SWAP_SIZE(x) ((x & 7) << 28)
+
+#define AWCACHE0 (1)
+#define AWCACHE1 (2)
+#define AWCACHE2 (4)
+#define DST_CACHE_CTRL_MASK (7 << 25)
+#define DST_CACHE_CTRL(x) ((x & 7) << 25)
+
+#define AWPROT0 (1)
+#define AWPROT1 (2)
+#define AWPROT2 (4)
+#define DST_PROT_CTRL_MASK (7 << 22)
+#define DST_PROT_CTRL(x) ((x & 7) << 22)
+
+/* Burst Len absolute value */
+#define DST_BURST_LEN_MASK (0xf << 18)
+#define DST_BURST_LEN(x) (((x - 1) & 0xf) << 18)
+
+#define BS_1 0
+#define BS_2 1
+#define BS_4 2
+#define BS_8 3
+#define DST_BURST_SIZE_MASK (7 << 15)
+#define DST_BURST_SIZE(x) ((x & 7) << 15)
+
+#define DST_INC (1 << 14)
+
+#define ARCACHE0 (1)
+#define ARCACHE1 (2)
+#define ARCACHE2 (4)
+#define SRC_CACHE_CTRL_MASK (7 << 11)
+#define SRC_CACHE_CTRL(x) ((x & 7) << 11)
+
+#define ARPROT0 (1)
+#define ARPROT1 (2)
+#define ARPROT2 (4)
+#define SRC_PROT_CTRL_MASK (7 << 8)
+#define SRC_PROT_CTRL(x) ((x & 7) << 8)
+
+/* Burst Len absolute value */
+#define SRC_BURST_LENGTH_MASK (0xf << 4)
+#define SRC_BURST_LENGTH(x) (((x - 1) & 0xf) << 4)
+
+/* Burst Size absolute value */
+#define SRC_BURST_SIZE_MASK (7 << 1)
+#define SRC_BURST_SIZE(x) ((x & 7) << 1)
+
+#define SRC_INC (1 << 0)
+
+#define LC0 0x0
+#define LC0_END 0x10
+#define LC1 0x2
+#define LC1_END 0x14
+
+#define CCR_M2M_DFLT (ENDIAN_SWAP_SIZE(NOSWAP) | \
+ DST_CACHE_CTRL(AWCACHE1) | \
+ DST_INC | \
+ SRC_CACHE_CTRL(ARCACHE1) | \
+ SRC_INC | \
+ SRC_PROT_CTRL(2) | \
+ DST_PROT_CTRL(2))
+
+#define CCR_P2P_DFLT (ENDIAN_SWAP_SIZE(NOSWAP) | \
+ DST_CACHE_CTRL(AWCACHE1) | \
+ SRC_CACHE_CTRL(ARCACHE1))
+
+#define CCR_P2M_DFLT (ENDIAN_SWAP_SIZE(NOSWAP) | \
+ DST_CACHE_CTRL(AWCACHE1) | \
+ DST_INC | \
+ SRC_CACHE_CTRL(ARCACHE1) | \
+ SRC_PROT_CTRL(2) | \
+ DST_PROT_CTRL(2))
+
+#define CCR_M2P_DFLT (ENDIAN_SWAP_SIZE(NOSWAP) | \
+ DST_CACHE_CTRL(AWCACHE1) | \
+ SRC_CACHE_CTRL(ARCACHE1) | \
+ SRC_INC | \
+ SRC_PROT_CTRL(2) | \
+ DST_PROT_CTRL(2))
+
+#define CCR_M2MP_DFLT (ENDIAN_SWAP_SIZE(NOSWAP) | \
+ DST_CACHE_CTRL(AWCACHE1) | \
+ SRC_CACHE_CTRL(ARCACHE1) | \
+ SRC_PROT_CTRL(2) | \
+ DST_PROT_CTRL(2))
+
+#define DMA_MC_4B_SET(a, b) (*(unsigned int *)(a) = (unsigned int)(b))
+#define DMA_MC_1B_SET(a, b) (*(char *)(a) = (char)(b))
+#define DMA_MC_EV_SET(a, b) (*(char *)(a) = (char)(b << 3))
+
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+typedef enum {
+ DMA_SAR = 0,
+ DMA_CCR,
+ DMA_DAR,
+} DMA_INST_REG;
+
+typedef enum {
+ DMA_LC0 = 0,
+ DMA_LC1,
+} DMA_LC;
+
+typedef enum {
+ DMA_CH0 = 0x0,
+ DMA_CH1,
+ DMA_CH2,
+ DMA_CH3,
+ DMA_CH4,
+ DMA_CH5,
+ DMA_CH6,
+ DMA_CH7
+} DMA_CHANNEL_NUM;
+
+
+typedef struct dma_drvdata dma_drvdata;
+
+typedef struct {
+ dma_drvdata *dma;
+ DMA_CHANNEL_NUM dma_chan_num;
+ u8 channel_assigned;
+
+ dma_task *task;
+
+} DMA_CH_CONTEXT;
+
+struct dma_drvdata {
+ char *name;
+ void *base;
+ int isr_num;
+ xcpt_t isr_handler;
+
+ /* struct dma_device *dev; */
+
+ /* Add private data structures if it is needed */
+ u32 max_ch_num;
+ u32 max_burst_len;
+ u32 max_burst_size; /* data_size */
+ /* bool dma_initialized; */
+ DMA_CH_CONTEXT dma_ch[DMAC_MAX_CH];
+};
+
+typedef enum {
+ m2m,
+ m2p,
+ p2m,
+ p2p,
+} mc_tmplt;
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+/* Microcode functions */
+inline static int DMA_Encode_DMAMOV(char *base, void **reg_addr, DMA_INST_REG rd)
+{
+ rd &= 0x07;
+
+ base[0] = 0xBC;
+ base[1] = rd;
+ base[2] = 0xd;
+ base[3] = 0xe;
+ base[4] = 0xa;
+ base[5] = 0xd;
+
+ *reg_addr = base + 2;
+ return 6;
+}
+
+inline static int DMA_Encode_DMALP(char *base, DMA_LC lc, void **iter)
+{
+
+ base[0] = 0x20 | lc;
+ base[1] = 0xe;
+
+ *iter = base + 1;
+ return 2;
+}
+
+inline static int DMA_Encode_DMALPEND(char *base, u8 CTRL, char backwards_jump)
+{
+ base[0] = 0x28 | CTRL;
+ base[1] = backwards_jump;
+ return 2;
+}
+
+inline static int DMA_Encode_DMALD(char *base, u8 CTRL)
+{
+ base[0] = 0x04 | CTRL;
+ return 1;
+}
+
+inline static int DMA_Encode_DMALDP(char *base, u8 CTRL, DMA_REQ_MAP periph)
+{
+ base[0] = 0x25 | CTRL;
+ base[1] = periph << 3;
+ return 2;
+}
+
+inline static int DMA_Encode_DMAST(char *base, u8 CTRL)
+{
+ base[0] = 0x08 | CTRL;
+ return 1;
+}
+
+inline static int DMA_Encode_DMASTP(char *base, u8 CTRL, DMA_REQ_MAP periph)
+{
+ base[0] = 0x29 | CTRL;
+ base[1] = periph << 3;
+ return 2;
+}
+
+inline static int DMA_Encode_DMAWFP(char *base, u8 CTRL, DMA_REQ_MAP periph)
+{
+ base[0] = 0x30 | CTRL;
+ base[1] = periph << 3;
+ return 2;
+}
+
+inline static int DMA_Encode_DMASEV(char *base, void **event_num)
+{
+ base[0] = 0x34;
+ base[1] = 0xe;
+ *event_num = base + 1;
+ return 2;
+}
+
+inline static int DMA_Encode_DMAEND(char *base)
+{
+ base[0] = 0x00;
+ return 1;
+}
+
+inline static int DMA_Encode_DMAFLUSHP(char *base, u8 periph)
+{
+ base[0] = 0x35;
+ base[1] = periph << 3;
+ return 2;
+}
+
+inline static int DMA_Encode_DMAWMB(char *base)
+{
+ base[0] = 0x13;
+ return 1;
+}
+
+#endif
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <tinyara/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <assert.h>
+#include <queue.h>
+#include <debug.h>
+
+#include <arch/board/board.h>
+
+#include <tinyara/irq.h>
+#include <tinyara/arch.h>
+#include <tinyara/kmalloc.h>
+#include <tinyara/wdog.h>
+#include <tinyara/wqueue.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+#include "cache.h"
+
+#include "chip.h"
+#include "s5j_dma.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+typedef struct d_dma_task_priv {
+ struct dma_task task;
+ int mc_array_size;
+ int mc_size;
+ int chflags;
+ void *SAR;
+ void *DAR;
+ void *CCR;
+ void *LOOP1;
+ void *LOOP0;
+ void *EVENT_CH;
+} t_dma_task_priv;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: s5j_dma_priv_setup
+ *
+ * Description:
+ * Private method to prepare mocrocode for DMA M2M operation.
+ *
+ * Input Parameters
+ * handle - DMA channel handle structure;
+ * task - DMA task structure with microcode to execute
+ *
+ * Returned Value:
+ * OK;
+ *
+ ****************************************************************************/
+static int s5j_dma_priv_setup(DMA_HANDLE handle, dma_task *task)
+{
+ t_dma_task_priv *priv_task = (t_dma_task_priv *) task;
+ DMA_CH_CONTEXT *ch;
+ ch = handle;
+
+ priv_task->chflags = CCR_M2M_DFLT |
+ SRC_BURST_SIZE(BS_4) |
+ DST_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);
+
+ DMA_MC_EV_SET(priv_task->EVENT_CH, ch->dma_chan_num);
+
+ arch_clean_dcache((uintptr_t)task->microcode,
+ (uintptr_t)(task->microcode + priv_task->mc_size));
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: dma_task_m2m_sb_4B_x256_alloc
+ *
+ * Description:
+ * This function allocated task structure for M2M DMA transfers microcode.
+ * It prepares microcode and place holders for loop counters and addresses.
+ *
+ * Input Parameters
+ * None
+ *
+ * Returned Value:
+ * Pointer on dma_task structure
+ *
+ ****************************************************************************/
+dma_task *dma_task_m2m_sb_4B_x256_alloc(void)
+{
+ dma_task *task;
+ t_dma_task_priv *priv_task;
+ void *mc_base;
+ void *loop_offs0;
+ void *loop_offs1;
+
+ task = zalloc(sizeof(t_dma_task_priv));
+ if (task == NULL) {
+ dmadbg("ERROR: Failed to allocate microcode memory\n");
+ return NULL;
+ }
+
+ task->microcode = zalloc(32);
+ if (task->microcode == NULL) {
+ dmadbg("ERROR: Failed to allocate microcode memory\n");
+ free(task);
+ return NULL;
+ }
+
+ priv_task = (t_dma_task_priv *) task;
+ priv_task->mc_array_size = 32;
+
+ mc_base = task->microcode;
+
+ 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_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 - LD & ST does not depend on burst L/S settings */
+ mc_base += DMA_Encode_DMALD(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);
+ 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->mc_size = mc_base - task->microcode;
+
+ task->setup = s5j_dma_priv_setup;
+ return task;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <tinyara/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <assert.h>
+#include <queue.h>
+#include <debug.h>
+
+#include <arch/board/board.h>
+
+#include <tinyara/irq.h>
+#include <tinyara/arch.h>
+#include <tinyara/kmalloc.h>
+#include <tinyara/wdog.h>
+#include <tinyara/wqueue.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+#include "cache.h"
+
+#include "chip.h"
+#include "s5j_dma.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+typedef struct d_dma_task_priv {
+ struct dma_task task;
+ int mc_array_size;
+ int mc_size;
+ int chflags;
+ void *SAR;
+ void *DAR;
+ void *CCR;
+ void *LOOP1;
+ void *LOOP0;
+ void *EVENT_CH;
+} t_dma_task_priv;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: s5j_dma_priv_setup
+ *
+ * Description:
+ * Private method to prepare mocrocode for DMA M2P operation.
+ *
+ * Input Parameters
+ * handle - DMA channel handle structure;
+ * task - DMA task structure with microcode to execute
+ *
+ * Returned Value:
+ * OK;
+ *
+ ****************************************************************************/
+static int s5j_dma_priv_setup(DMA_HANDLE handle, dma_task *task)
+{
+ t_dma_task_priv *priv_task = (t_dma_task_priv *) task;
+ DMA_CH_CONTEXT *ch;
+ ch = handle;
+
+ priv_task->chflags = CCR_M2P_DFLT |
+ SRC_BURST_SIZE(BS_1) |
+ DST_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);
+
+ DMA_MC_EV_SET(priv_task->EVENT_CH, ch->dma_chan_num);
+
+ arch_clean_dcache((uintptr_t)task->microcode,
+ (uintptr_t)(task->microcode + priv_task->mc_size));
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: dma_task_m2p_sb_4B_x256_alloc
+ *
+ * Description:
+ * This function allocated task structure for M2P DMA transfers microcode.
+ * It prepares microcode and place holders for loop counters and addresses.
+ *
+ * Input Parameters
+ * d_ph_ch - destination peripheral DMA shannel number
+ *
+ * Returned Value:
+ * Pointer on dma_task structure
+ *
+ ****************************************************************************/
+dma_task *dma_task_m2p_sb_4B_x256_alloc(DMA_REQ_MAP d_ph_ch)
+{
+ dma_task *task;
+ t_dma_task_priv *priv_task;
+ void *mc_base;
+ void *loop_offs0;
+ void *loop_offs1;
+
+ task = zalloc(sizeof(t_dma_task_priv));
+ if (task == NULL) {
+ dmadbg("ERROR: Failed to allocate microcode memory\n");
+ return NULL;
+ }
+
+ task->microcode = zalloc(64);
+ if (task->microcode == NULL) {
+ dmadbg("ERROR: Failed to allocate microcode memory\n");
+ free(task);
+ return NULL;
+ }
+
+ priv_task = (t_dma_task_priv *) task;
+ priv_task->mc_array_size = 64;
+
+ mc_base = task->microcode;
+
+ 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 */
+ 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);
+
+ /* 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);
+
+ /* 0 - STP singles / NOP burst */
+ mc_base += DMA_Encode_DMASTP(mc_base, 0, d_ph_ch);
+
+ /* 2 - NOP singles / STP burst */
+ mc_base += DMA_Encode_DMASTP(mc_base, 2, d_ph_ch);
+
+ mc_base += DMA_Encode_DMAFLUSHP(mc_base, d_ph_ch);
+
+ /*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);
+
+ 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->mc_size = mc_base - task->microcode;
+
+ task->setup = s5j_dma_priv_setup;
+ return task;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <tinyara/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <assert.h>
+#include <queue.h>
+#include <debug.h>
+
+#include <arch/board/board.h>
+
+#include <tinyara/irq.h>
+#include <tinyara/arch.h>
+#include <tinyara/kmalloc.h>
+#include <tinyara/wdog.h>
+#include <tinyara/wqueue.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+#include "cache.h"
+
+#include "chip.h"
+#include "s5j_dma.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+typedef struct d_dma_task_priv {
+ struct dma_task task;
+ int mc_array_size;
+ int mc_size;
+ int chflags;
+ void *SAR;
+ void *DAR;
+ void *CCR;
+ void *LOOP1;
+ void *LOOP0;
+ void *EVENT_CH;
+} t_dma_task_priv;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: s5j_dma_priv_setup
+ *
+ * Description:
+ * Private method to prepare mocrocode for DMA P2M operation.
+ *
+ * Input Parameters
+ * handle - DMA channel handle structure;
+ * task - DMA task structure with microcode to execute
+ *
+ * Returned Value:
+ * OK;
+ *
+ ****************************************************************************/
+static int s5j_dma_priv_setup(DMA_HANDLE handle, dma_task *task)
+{
+ t_dma_task_priv *priv_task = (t_dma_task_priv *) task;
+ DMA_CH_CONTEXT *ch;
+ ch = handle;
+
+ priv_task->chflags = CCR_P2M_DFLT |
+ SRC_BURST_SIZE(BS_4) |
+ DST_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);
+
+ DMA_MC_EV_SET(priv_task->EVENT_CH, ch->dma_chan_num);
+
+ arch_clean_dcache((uintptr_t)task->microcode,
+ (uintptr_t)(task->microcode + priv_task->mc_size));
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: dma_task_p2m_sb_4B_x256_alloc
+ *
+ * Description:
+ * This function allocated task structure for M2P DMA transfers microcode.
+ * It prepares microcode and place holders for loop counters and addresses.
+ *
+ * Input Parameters
+ * s_ph_ch - source peripheral DMA shannel number
+ *
+ * Returned Value:
+ * Pointer on dma_task structure
+ *
+ ****************************************************************************/
+dma_task *dma_task_p2m_sb_4B_x256_alloc(DMA_REQ_MAP s_ph_ch)
+{
+ dma_task *task;
+ t_dma_task_priv *priv_task;
+ void *mc_base;
+ void *loop_offs0;
+ void *loop_offs1;
+
+ task = zalloc(sizeof(t_dma_task_priv));
+ if (task == NULL) {
+ dmadbg("ERROR: Failed to allocate microcode memory\n");
+ return NULL;
+ }
+
+ task->microcode = zalloc(64);
+ if (task->microcode == NULL) {
+ dmadbg("ERROR: Failed to allocate microcode memory\n");
+ free(task);
+ return NULL;
+ }
+
+ priv_task = (t_dma_task_priv *) task;
+ priv_task->mc_array_size = 64;
+
+ mc_base = task->microcode;
+
+ 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 */
+ 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);
+
+ /* 0 - LDP singles / NOP burst */
+ mc_base += DMA_Encode_DMALDP(mc_base, 0, s_ph_ch);
+
+ /* 2 - NOP singles / STP burst */
+ mc_base += DMA_Encode_DMALDP(mc_base, 2, 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_DMAFLUSHP(mc_base, s_ph_ch);
+
+ /*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);
+
+ mc_base += DMA_Encode_DMASEV(mc_base, &(priv_task->EVENT_CH));
+ mc_base += DMA_Encode_DMAEND(mc_base);
+
+ priv_task->mc_size = mc_base - task->microcode;
+
+ task->setup = s5j_dma_priv_setup;
+ return task;
+}
#define ttdbg(format, ...)
#endif
-
#else /* CONFIG_CPP_HAVE_VARARGS */
/* Variadic macros NOT supported */