s5j/dma: Add dma driver for i2s
authorIvan <ivan.galkin@samsung.com>
Tue, 30 May 2017 08:30:53 +0000 (17:30 +0900)
committerIvan Galkin <ivan.galkin@samsung.com>
Sun, 27 Aug 2017 05:27:21 +0000 (14:27 +0900)
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>
os/arch/arm/include/s5j/dma.h [new file with mode: 0644]
os/arch/arm/src/s5j/Kconfig
os/arch/arm/src/s5j/Make.defs
os/arch/arm/src/s5j/s5j_dma.c [new file with mode: 0644]
os/arch/arm/src/s5j/s5j_dma.h [new file with mode: 0644]
os/arch/arm/src/s5j/s5j_dma_m2m_sb_4B_x256.c [new file with mode: 0644]
os/arch/arm/src/s5j/s5j_dma_m2p_sb_4B_x256.c [new file with mode: 0644]
os/arch/arm/src/s5j/s5j_dma_p2m_sb_4B_x256.c [new file with mode: 0644]
os/include/debug.h

diff --git a/os/arch/arm/include/s5j/dma.h b/os/arch/arm/include/s5j/dma.h
new file mode 100644 (file)
index 0000000..481d610
--- /dev/null
@@ -0,0 +1,103 @@
+/****************************************************************************
+ *
+ * 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
index 374d667..6dafa17 100644 (file)
@@ -25,6 +25,7 @@ config S5J_S5JT200
        bool
        default n
        select S5J_HAVE_ADC
+       select S5J_HAVE_DMA
        select S5J_HAVE_I2C
        select S5J_HAVE_I2S
        select S5J_HAVE_MCT
@@ -55,6 +56,10 @@ config S5J_HAVE_ADC
        bool
        default n
 
+config S5J_HAVE_DMA
+       bool
+       default n
+
 config S5J_HAVE_I2C
        bool
        default n
@@ -147,6 +152,11 @@ config S5J_ADC
                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
index c023f53..89299a4 100644 (file)
@@ -133,6 +133,13 @@ ifeq ($(CONFIG_S5J_ADC),y)
 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
diff --git a/os/arch/arm/src/s5j/s5j_dma.c b/os/arch/arm/src/s5j/s5j_dma.c
new file mode 100644 (file)
index 0000000..8a03d0a
--- /dev/null
@@ -0,0 +1,467 @@
+/****************************************************************************
+ *
+ * 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);
+}
diff --git a/os/arch/arm/src/s5j/s5j_dma.h b/os/arch/arm/src/s5j/s5j_dma.h
new file mode 100644 (file)
index 0000000..7cc3e29
--- /dev/null
@@ -0,0 +1,332 @@
+/****************************************************************************
+ *
+ * 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
diff --git a/os/arch/arm/src/s5j/s5j_dma_m2m_sb_4B_x256.c b/os/arch/arm/src/s5j/s5j_dma_m2m_sb_4B_x256.c
new file mode 100644 (file)
index 0000000..45388e7
--- /dev/null
@@ -0,0 +1,177 @@
+/****************************************************************************
+ *
+ * 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;
+}
diff --git a/os/arch/arm/src/s5j/s5j_dma_m2p_sb_4B_x256.c b/os/arch/arm/src/s5j/s5j_dma_m2p_sb_4B_x256.c
new file mode 100644 (file)
index 0000000..9574230
--- /dev/null
@@ -0,0 +1,194 @@
+/****************************************************************************
+ *
+ * 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;
+}
diff --git a/os/arch/arm/src/s5j/s5j_dma_p2m_sb_4B_x256.c b/os/arch/arm/src/s5j/s5j_dma_p2m_sb_4B_x256.c
new file mode 100644 (file)
index 0000000..b4dede4
--- /dev/null
@@ -0,0 +1,193 @@
+/****************************************************************************
+ *
+ * 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;
+}
index a374bb0..5121468 100644 (file)
@@ -630,7 +630,6 @@ Once LOGM is approved, each module should have its own index
 #define ttdbg(format, ...)
 #endif
 
-
 #else                                                  /* CONFIG_CPP_HAVE_VARARGS */
 
 /* Variadic macros NOT supported */