This patch adds DMA pl330 mico code for S5P series in plat-samsung.This patch 
also
moves some common code from s3c2410 to plat-samsung which can also be used by 
pl330.

Signed-off-by: Atul Dahiya <[email protected]>
---
 arch/arm/mach-s3c2410/include/mach/dma.h           |   12 +-
 arch/arm/plat-samsung/Kconfig                      |    5 +
 arch/arm/plat-samsung/Makefile                     |    2 +-
 arch/arm/plat-samsung/dma-pl330-mcode.c            |  671 ++++++++++++++++++++
 arch/arm/plat-samsung/include/plat/cpu.h           |    1 +
 .../plat-samsung/include/plat/dma-pl330-mcode.h    |  103 +++
 arch/arm/plat-samsung/include/plat/dma.h           |   59 ++-
 7 files changed, 843 insertions(+), 10 deletions(-)
 create mode 100644 arch/arm/plat-samsung/dma-pl330-mcode.c
 create mode 100644 arch/arm/plat-samsung/include/plat/dma-pl330-mcode.h

diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h 
b/arch/arm/mach-s3c2410/include/mach/dma.h
index 08ac5f9..316e0cc 100644
--- a/arch/arm/mach-s3c2410/include/mach/dma.h
+++ b/arch/arm/mach-s3c2410/include/mach/dma.h
@@ -61,13 +61,13 @@ enum dma_ch {
 #endif
 
 /* types */
-
+/*
 enum s3c2410_dma_state {
        S3C2410_DMA_IDLE,
        S3C2410_DMA_RUNNING,
        S3C2410_DMA_PAUSED
 };
-
+*/
 /* enum s3c2410_dma_loadst
  *
  * This represents the state of the DMA engine, wrt to the loaded / running
@@ -95,14 +95,14 @@ enum s3c2410_dma_state {
  * There is a buffer waiting to be loaded by the DMA engine, and one
  * currently running.
 */
-
+/*
 enum s3c2410_dma_loadst {
        S3C2410_DMALOAD_NONE,
        S3C2410_DMALOAD_1LOADED,
        S3C2410_DMALOAD_1RUNNING,
        S3C2410_DMALOAD_1LOADED_1RUNNING,
 };
-
+*/
 
 /* flags */
 
@@ -132,7 +132,7 @@ struct s3c2410_dma_buf {
 };
 
 /* [1] is this updated for both recv/send modes? */
-
+/*
 struct s3c2410_dma_stats {
        unsigned long           loads;
        unsigned long           timeout_longest;
@@ -140,7 +140,7 @@ struct s3c2410_dma_stats {
        unsigned long           timeout_avg;
        unsigned long           timeout_failed;
 };
-
+*/
 struct s3c2410_dma_map;
 
 /* struct s3c2410_dma_chan
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index d552c65..39b42eb 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -69,6 +69,11 @@ config SAMSUNG_IRQ_UART
        help
          Internal configuration to build the IRQ UART demux code.
 
+config SAMSUNG_PL_330
+       bool
+       help
+       Select pl-330 code for all SAMSUNG S5P SOCs.
+
 # options for gpio configuration support
 
 config SAMSUNG_GPIOLIB_4BIT
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 22c89d0..32c57b0 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -44,7 +44,7 @@ obj-$(CONFIG_S3C_DEV_NAND)    += dev-nand.o
 # DMA support
 
 obj-$(CONFIG_S3C_DMA)          += dma.o
-
+obj-$(CONFIG_SAMSUNG_PL_330)   += dma-pl330-mcode.o
 # PM support
 
 obj-$(CONFIG_PM)               += pm.o
diff --git a/arch/arm/plat-samsung/dma-pl330-mcode.c 
b/arch/arm/plat-samsung/dma-pl330-mcode.c
new file mode 100644
index 0000000..ec6e8e7
--- /dev/null
+++ b/arch/arm/plat-samsung/dma-pl330-mcode.c
@@ -0,0 +1,671 @@
+/* linux/arch/arm/plat-s5p/dma-pl330-mcode.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *             http://www.samsung.com/
+ *
+ * DMA PL330 microcode
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/io.h>
+#include "plat/dma-pl330-mcode.h"
+
+/* DMAMOV CCR, ...  */
+int encode_dma_move_ch_ctrl(u8 *mcode_ptr, u32 dmacon)
+{
+       writeb(DMAMOV, mcode_ptr++);
+       writeb(0x1, mcode_ptr++);
+       writel(dmacon, mcode_ptr);
+       return 6;
+}
+
+/* DMAMOV SAR, uStAddr
+ * DMAMOV DAR, uStAddr
+ * DMAMOV CCR,  */
+int encode_dma_move(u8 *mcode_ptr, u8 uDir, u32 uStAddr)
+{
+       writeb(DMAMOV, mcode_ptr++);
+       writeb(uDir, mcode_ptr++);
+       writel(uStAddr, mcode_ptr);
+       return 6;
+}
+
+/* DMALD */
+int encode_dma_load(u8 *mcode_ptr)
+{
+       writeb(DMALD, mcode_ptr);
+       return 1;
+
+}
+
+/* DMALDS */
+int encode_dma_load_s(u8 *mcode_ptr)
+{
+       writeb(DMALDS, mcode_ptr);
+       return 1;
+
+}
+
+/* DMALDB  */
+int encode_dma_load_b(u8 *mcode_ptr)
+{
+        writeb(DMALDB, mcode_ptr);
+       return 1;
+
+}
+
+/* DMALDPS, DMALDPB (Load Peripheral)  */
+int encode_dma_load_peri(u8 *mcode_ptr, u8 mPeriNum, u8 m_uBurstSz)
+{
+       u8 bs;
+       if (mPeriNum > PL330_MAX_PERIPHERAL_NUM) {
+               print_warning("[%s] The peripheral number is"
+                               "too big ! : %d\n", __func__, mPeriNum);
+               return 0;
+       }
+       bs = (m_uBurstSz == 1) ? 0 : 1; /* single -> 0, burst -> 1 */
+       writeb((DMALDPS|(bs<<1)), mcode_ptr++);
+       writeb(mPeriNum << 3, mcode_ptr);
+
+       return 2;
+}
+
+/* DMAST  */
+static int encode_dma_store(u8 *mcode_ptr)
+{
+       u8 opcode = DMAST;
+       writeb(opcode, mcode_ptr);
+       return 1;
+}
+
+/* DMASTS */
+static int encode_dma_store_single(u8 *mcode_ptr)
+{
+       u8 opcode = DMASTS;
+       writeb(opcode, mcode_ptr);
+       return 1;
+}
+
+/*DMASTB  */
+static int encode_dma_store_brust(u8 *mcode_ptr)
+{
+       u8 opcode = DMASTB;
+       writeb(opcode, mcode_ptr);
+       return 1;
+}
+
+/* DMASTPS, DMASTPB (Store and notify Peripheral)  */
+int encode_dma_store_peri(u8 *mcode_ptr, u8 mPeriNum, u8 m_uBurstSz)
+{
+       u8 bs;
+       if (mPeriNum > PL330_MAX_PERIPHERAL_NUM) {
+               print_warning("[%s] The peripheral number is too"
+                                       "big ! : %d\n", __func__, mPeriNum);
+               return 0;
+       }
+       bs = (m_uBurstSz == 1) ? 0 : 1; /* single:0, burst:1 */
+       writeb((DMASTPS|(bs<<1)), mcode_ptr++);
+       writeb(mPeriNum << 3, mcode_ptr);
+       return 2;
+}
+
+/* DMASTZ  */
+int encode_dma_store_zero(u8 *mcode_ptr)
+{
+       writeb(DMASTZ , mcode_ptr);
+       return 1;
+}
+
+/* DMALP  */
+static int encode_dma_loop(u8 *mcode_ptr, u8 uLoopCnt, u8 uIteration)
+{
+       u8 opcode = DMALP | (uLoopCnt << 1);
+       writeb(opcode, mcode_ptr++);
+       writeb(uIteration, mcode_ptr);
+       return 2;
+}
+
+/* DMALPFE  */
+static int encode_dma_loop_forever(u8 *mcode_ptr, u8 uBwJump)
+{
+       writeb(DMALPFE, mcode_ptr++);
+       writeb(uBwJump, mcode_ptr);
+       return 2;
+}
+
+/* DMALPEND */
+static int encode_dma_loop_end(u8 *mcode_ptr, u8 uLoopCnt, u8 uBwJump)
+{
+       u8 opcode = DMALPEND | (uLoopCnt << 2);
+       writeb(opcode, mcode_ptr++);
+       writeb(uBwJump, mcode_ptr);
+       return 2;
+}
+
+/* DMALPENDS */
+static int encode_dma_loop_ends(u8 *mcode_ptr, u8 uLoopCnt, u8 uBwJump)
+{
+       u8 opcode = DMALPENDS | (uLoopCnt << 2);
+       writeb(opcode, mcode_ptr++);
+       writeb(uBwJump, mcode_ptr);
+       return 2;
+}
+
+/* DMALPENDB  */
+static int encode_dma_loop_endb(u8 *mcode_ptr, u8 uLoopCnt, u8 uBwJump)
+{
+       u8 opcode = DMALPENDB | (uLoopCnt << 2);
+       writeb(opcode, mcode_ptr++);
+       writeb(uBwJump, mcode_ptr);
+       return 2;
+}
+
+/*  DMAWFPS (Wait For Peripheral) */
+static int encode_dma_wait_for_peri(u8 *mcode_ptr, u8 mPeriNum)
+{
+       u8 opcode = DMAWFPS;
+       writeb(opcode, mcode_ptr++);
+       writeb(mPeriNum << 3, mcode_ptr);
+       return 2;
+}
+
+/*  DMAWFPB (Wait For Peripheral)
+static int encode_dma_wait_for_peri(u8 *mcode_ptr, u8 mPeriNum)
+{
+       u8 opcode = DMAWFPB;
+       writeb(opcode, mcode_ptr++);
+       writeb(mPeriNum << 3, mcode_ptr);
+       return 2;
+}
+
+/  DMAWFP (Wait For Peripheral) /
+static int encode_dma_wait_for_peri(u8 *mcode_ptr, u8 mPeriNum)
+{
+       u8 opcode = DMAWFP;
+       writeb(opcode, mcode_ptr++);
+       writeb(mPeriNum << 3, mcode_ptr);
+       return 2;
+}
+
+  DMAFLUSHP (Flush and notify Peripheral) */
+static int encode_dma_flush_peri(u8 *mcode_ptr, u8 mPeriNum)
+{
+       u8 opcode = DMAFLUSHP;
+       writeb(opcode, mcode_ptr++);
+       writeb(mPeriNum << 3, mcode_ptr);
+       return 2;
+}
+
+/* DMAEND */
+static int encode_dma_end(u8 *mcode_ptr)
+{
+       u8 opcode = DMAEND;
+       writeb(opcode, mcode_ptr);
+       return 1;
+}
+
+/* DMARMB (Read Memory Barrier) */
+static int encode_dma_read_mem_barrier(u8 *mcode_ptr)
+{
+       u8 opcode = DMARMB;
+       writeb(opcode, mcode_ptr);
+       return 1;
+}
+
+/* DMASEV (Send Event) : 0 ~ 31 */
+static int encode_dma_send_event(u8 *mcode_ptr, u8 uEventNum)
+{
+       u8 opcode = DMASEV;
+       writeb(opcode, mcode_ptr++);
+       writeb(uEventNum << 3, mcode_ptr);
+       return 2;
+}
+
+/* DMAGO over DBGINST[0:1] registers */
+static void encode_dma_go_over_dbginst(u32 *mcode_ptr, u8 chanNum,
+                                       u32 mbufAddr, u8 m_secureBit)
+{
+       u32 x;
+       u8 uDmaGo;              /* DMAGO instruction */
+       if (chanNum > PL330_MAX_CHANNEL_NUM) {
+               print_warning("[%s] Channel num big: %d\n", __func__, chanNum);
+               return;
+       }
+       do {
+               x = Inp32(mcode_ptr+DMA_DBGSTATUS);
+       } while ((x&0x1) == 0x1);
+       uDmaGo = (m_secureBit == 0) ?
+               (0xa0|(0<<1)) :         /* secure mode : M2M DMA only   */
+               (0xa0|(1<<1));          /* non-secure mode : M2P/P2M DMA only */
+       Outp32(mcode_ptr+DMA_DBGINST0,
+               (chanNum<<24)|(uDmaGo<<16)|(chanNum<<8)|(0<<0));
+       Outp32(mcode_ptr+DMA_DBGINST1, mbufAddr);
+       Outp32(mcode_ptr+DMA_DBGCMD, 0);
+
+}
+
+/* DMAKILL over DBGINST[0:1] registers - Stop a DMA channel */
+static void encode_dma_kill_channel_over_dbginst(u32 *mcode_ptr, u8 chanNum)
+{
+       u32 x;
+       if (chanNum > PL330_MAX_CHANNEL_NUM) {
+               print_warning("[%s] Channel num big: %d\n", __func__, chanNum);
+               return;
+       }
+       do {
+               x = Inp32(mcode_ptr+DMA_DBGSTATUS);
+       } while ((x&0x1) == 0x1);
+       Outp32(mcode_ptr+DMA_DBGINST0, (0<<24)|(1<<16)|(chanNum<<8)|(1<<0));
+       Outp32(mcode_ptr+DMA_DBGINST1, 0);
+       Outp32(mcode_ptr+DMA_DBGCMD, 0);
+       do {
+               x = Inp32(mcode_ptr+DMA_DBGSTATUS);
+       } while ((x&0x1) == 0x1);
+}
+
+/* DMAKILL over DBGINST[0:1] registers - Stop a DMA controlle*/
+static void encode_dma_kill_dmac_over_dbginst(u32 *mcode_ptr)
+{
+       u32 x;
+       do {
+               x = Inp32(mcode_ptr+DMA_DBGSTATUS);
+       } while ((x&0x1) == 0x1);
+
+       Outp32(mcode_ptr+DMA_DBGINST0, (0<<24)|(1<<16)|(0<<8)|(0<<0));
+       Outp32(mcode_ptr+DMA_DBGINST1, 0);
+       Outp32(mcode_ptr+DMA_DBGCMD, 0);        /* 0 : execute the instruction*/
+
+       do {
+               x = Inp32(mcode_ptr+DMA_DBGSTATUS);
+       } while ((x&0x1) == 0x1);
+}
+
+/* config_dma_start_address
+ * - set the DMA start address
+ *
+ *     mcode_ptr       the pointer to the buffer for PL330 DMAMOVE micro code
+ *                     to be stored into
+ *     uStAddr         the DMA start address
+ */
+static int config_dma_start_address(u8 *mcode_ptr, int uStAddr)
+{
+       return encode_dma_move(mcode_ptr, 0, (u32)uStAddr);
+}
+
+/* config_dma_destination_address
+ * - set the DMA destination address
+ *     mcode_ptr       the pointer to the buffer for PL330 DMAMOVE micro
+ *                     code to be stored into
+ *     uStAddr         the DMA destination address
+ */
+static int config_dma_destination_address(u8 *mcode_ptr, int uStAddr)
+{
+       return encode_dma_move(mcode_ptr, 2, (u32)uStAddr);
+}
+
+/* config_dma_control
+ * - set the burst length, burst size, source and destination increment/fixed
+ *   field
+ *     mcode_ptr       the pointer to the buffer for PL330 DMAMOVE micro
+ *                     code to be stored into
+ *     dmacon          the value for the DMA channel control register
+ */
+static int config_dma_control(u8 *mcode_ptr,  struct DMA_control dmacon)
+{
+       return encode_dma_move(mcode_ptr, 1, *(u32 *)&dmacon);
+}
+
+/* config_dma_transfer_remainder
+ * - set the transfer size of the remainder
+ *     mcode_ptr       the pointer to the buffer for PL330 DMADMA micro code
+ *                     to be stored into
+ *     lcRemainder     the remainder except for the LC-aligned transfers
+ *     dma_param       the parameter set for a DMA operation
+ */
+static int config_dma_transfer_remainder(u8 *mcode_ptr, int lcRemainder,
+                                       struct DMA_parameters dma_param)
+{
+       int mcode_size = 0, msize = 0;
+       int lc0 = 0, lcSize = 0, mLoopStart0 = 0, dmaSent = 0;
+       dmaSent = dma_param.mTrSize - lcRemainder;
+       msize = config_dma_start_address(mcode_ptr+mcode_size,
+                                       dma_param.mSrcAddr+dmaSent);
+       mcode_size += msize;
+       msize = config_dma_destination_address(mcode_ptr+mcode_size,
+                                       dma_param.mDstAddr+dmaSent);
+       mcode_size += msize;
+       dma_param.mControl.uSBSize = 0x2;       /* 4 bytes    */
+       dma_param.mControl.uSBLength = 0x0;     /* 1 transfer */
+       dma_param.mControl.uDBSize = 0x2;       /* 4 bytes    */
+       dma_param.mControl.uDBLength = 0x0;     /* 1 transfer */
+       msize = config_dma_control(mcode_ptr+mcode_size,
+                                       dma_param.mControl);
+       mcode_size += msize;
+       lcSize = (dma_param.mControl.uSBLength+1)*
+                       (1<<dma_param.mControl.uSBSize);
+       lc0 = lcRemainder/lcSize;
+       msize = encode_dma_loop(mcode_ptr+mcode_size, 0, lc0-1);
+       mcode_size += msize;
+       mLoopStart0 = mcode_size;
+       switch (dma_param.mDirection) {
+       case PL330_M2M_DMA:
+               msize = encode_dma_load(mcode_ptr+mcode_size);
+               mcode_size += msize;
+               msize = encode_dma_store(mcode_ptr+mcode_size);
+               mcode_size += msize;
+               break;
+       case PL330_M2P_DMA:
+               msize = encode_dma_wait_for_peri(mcode_ptr+mcode_size,
+                                               (u8)dma_param.mPeriNum);
+               mcode_size += msize;
+               msize = encode_dma_load(mcode_ptr+mcode_size);
+               mcode_size += msize;
+               msize = encode_dma_store_peri(mcode_ptr+mcode_size,
+                                       (u8)dma_param.mPeriNum, 1);
+               mcode_size += msize;
+               msize = encode_dma_flush_peri(mcode_ptr+mcode_size,
+                                               (u8)dma_param.mPeriNum);
+               mcode_size += msize;
+               break;
+       case PL330_P2M_DMA:
+               msize = encode_dma_wait_for_peri(mcode_ptr+mcode_size,
+                                               (u8)dma_param.mPeriNum);
+               mcode_size += msize;
+               msize = encode_dma_load_peri(mcode_ptr+mcode_size,
+                                               (u8)dma_param.mPeriNum, 1);
+               mcode_size += msize;
+               msize = encode_dma_store(mcode_ptr+mcode_size);
+               mcode_size += msize;
+               msize = encode_dma_flush_peri(mcode_ptr+mcode_size,
+                                       (u8)dma_param.mPeriNum);
+               mcode_size += msize;
+               break;
+       case PL330_P2P_DMA:
+               print_warning("[%s] P2P DMA selected !\n", __func__);
+               break;
+       default:
+               print_warning("[%s] Invaild DMA direction"
+                                       "selected !\n", __func__);
+               break;
+       }
+       msize = encode_dma_loop_end(mcode_ptr+mcode_size, 0,
+                               (u8)(mcode_size-mLoopStart0));
+       mcode_size += msize;
+       return mcode_size;
+}
+
+/* config_dma_transfer_size
+ * - set the transfer size
+ *     mcode_ptr       the pointer to the buffer for PL330 DMA micro code into
+ *     dma_param       the parameter set for a DMA operation
+ */
+static int config_dma_transfer_size(u8 *mcode_ptr,
+                       struct DMA_parameters dma_param)
+{
+       int mcode_size = 0, msize = 0;
+       int lc0 = 0, lc1 = 0, lcRemainder = 0, lcSize = 0;
+       int mLoopStart0 = 0, mLoopStart1 = 0;
+       switch (dma_param.mDirection) {
+       case PL330_M2M_DMA:
+               if (dma_param.mTrSize > (8*1024*1024)) {
+                       print_warning("[%s] The chunk size is too big"
+                                       "%lu\n", __func__, dma_param.mTrSize);
+                       return 0;
+               }
+               break;
+       case PL330_M2P_DMA:
+       case PL330_P2M_DMA:
+               if (dma_param.mTrSize > (2*1024*1024)) {
+                       print_warning("[%s] The chunk size is too"
+                               "big !: %lu\n", __func__, dma_param.mTrSize);
+                       return 0;
+               }
+               break;
+       case PL330_P2P_DMA:
+               print_warning("[%s] P2P DMA selected !\n", __func__);
+               break;
+       default:
+               print_warning("[%s] Invaild DMA direction entered\n", __func__);
+               break;
+       }
+       lcSize = (dma_param.mControl.uSBLength+1)*
+                       (1<<dma_param.mControl.uSBSize);
+       lc0 = dma_param.mTrSize/lcSize;
+       lcRemainder = dma_param.mTrSize - (lc0*lcSize);
+       if (lc0 > PL330_MAX_ITERATION_NUM) {
+               lc1 = lc0/PL330_MAX_ITERATION_NUM;
+               if (lc1 <= PL330_MAX_ITERATION_NUM) {
+                       msize = encode_dma_loop(mcode_ptr+mcode_size, 1, lc1-1);
+                       mcode_size += msize;
+                       mLoopStart1 = mcode_size;
+                       msize = encode_dma_loop(mcode_ptr+mcode_size, 0,
+                                               PL330_MAX_ITERATION_NUM-1);
+                       mcode_size += msize;
+                       mLoopStart0 = mcode_size;
+                       switch (dma_param.mDirection) {
+                       case PL330_M2M_DMA:
+                               msize = encode_dma_load(mcode_ptr+mcode_size);
+                               mcode_size += msize;
+                               msize = encode_dma_read_mem_barrier(mcode_ptr+
+                                                               mcode_size);
+                               mcode_size += msize;
+                               msize = encode_dma_store(mcode_ptr+mcode_size);
+                               mcode_size += msize;
+                               break;
+                       case PL330_M2P_DMA:
+                               msize = encode_dma_wait_for_peri(mcode_ptr +
+                                       mcode_size, (u8)dma_param.mPeriNum);
+                               mcode_size += msize;
+                               msize = encode_dma_load(mcode_ptr+mcode_size);
+                               mcode_size += msize;
+                               msize = encode_dma_store_peri(mcode_ptr +
+                                       mcode_size, (u8)dma_param.mPeriNum, 1);
+                               mcode_size += msize;
+                               msize = encode_dma_flush_peri(mcode_ptr +
+                                       mcode_size, (u8)dma_param.mPeriNum);
+                               mcode_size += msize;
+                               break;
+                       case PL330_P2M_DMA:
+                       msize = encode_dma_wait_for_peri(mcode_ptr + mcode_size,
+                                               (u8)dma_param.mPeriNum);
+                               mcode_size += msize;
+                               msize = encode_dma_load_peri(mcode_ptr +
+                                       mcode_size, (u8)dma_param.mPeriNum, 1);
+                               mcode_size += msize;
+                               msize = encode_dma_store(mcode_ptr +
+                                                               mcode_size);
+                               mcode_size += msize;
+                               msize = encode_dma_flush_peri(mcode_ptr +
+                                       mcode_size, (u8)dma_param.mPeriNum);
+                               mcode_size += msize;
+                               break;
+                       case PL330_P2P_DMA:
+                               print_warning("[%s] P2P DMA!\n", __func__);
+                               break;
+                       default:
+                               print_warning("[%s] Invaild DMA direction"
+                                               "selected !\n", __func__);
+                               break;
+                       }
+                       msize = encode_dma_loop_end(mcode_ptr + mcode_size, 0,
+                                               (u8)(mcode_size-mLoopStart0));
+                       mcode_size += msize;
+                       msize = encode_dma_loop_end(mcode_ptr + mcode_size, 1,
+                                               (u8)(mcode_size-mLoopStart1));
+                       mcode_size += msize;
+                       lc0 = lc0 - (lc1*PL330_MAX_ITERATION_NUM);
+               } else {
+                       print_warning("[%s] The transfer size is over the"
+                                       "limit (lc1=%d)\n", __func__, lc1);
+               }
+       }
+
+       if (lc0 > 0) {
+               msize = encode_dma_loop(mcode_ptr+mcode_size, 0, lc0-1);
+               mcode_size += msize;
+               mLoopStart0 = mcode_size;
+               switch (dma_param.mDirection) {
+               case PL330_M2M_DMA:
+                       msize = encode_dma_load(mcode_ptr + mcode_size);
+                       mcode_size += msize;
+                       msize = encode_dma_store(mcode_ptr + mcode_size);
+                       mcode_size += msize;
+                       break;
+               case PL330_M2P_DMA:
+                       msize = encode_dma_wait_for_peri(mcode_ptr + mcode_size,
+                                                       (u8)dma_param.mPeriNum);
+                       mcode_size += msize;
+                       msize = encode_dma_load(mcode_ptr + mcode_size);
+                       mcode_size += msize;
+                       msize = encode_dma_store_peri(mcode_ptr + mcode_size,
+                                               (u8)dma_param.mPeriNum, 1);
+                       mcode_size += msize;
+                       msize = encode_dma_flush_peri(mcode_ptr+mcode_size,
+                                               (u8)dma_param.mPeriNum);
+                       mcode_size += msize;
+                       break;
+               case PL330_P2M_DMA:
+                       msize = encode_dma_wait_for_peri(mcode_ptr + mcode_size,
+                                                       (u8)dma_param.mPeriNum);
+                       mcode_size += msize;
+                       msize = encode_dma_load_peri(mcode_ptr + mcode_size,
+                                               (u8)dma_param.mPeriNum, 1);
+                       mcode_size += msize;
+                       msize = encode_dma_store(mcode_ptr+mcode_size);
+                       mcode_size += msize;
+                       msize = encode_dma_flush_peri(mcode_ptr+mcode_size,
+                                               (u8)dma_param.mPeriNum);
+                       mcode_size += msize;
+                       break;
+               case PL330_P2P_DMA:
+                       print_warning("[%s] P2P DMA selected !\n", __func__);
+                       break;
+               default:
+                       break;
+               }
+               msize = encode_dma_loop_end(mcode_ptr+mcode_size, 0,
+                                       (u8)(mcode_size-mLoopStart0));
+               mcode_size += msize;
+       }
+       if (lcRemainder != 0) {
+               msize = config_dma_transfer_remainder(mcode_ptr+mcode_size,
+                                                       lcRemainder, dma_param);
+               mcode_size += msize;
+       }
+       return mcode_size;
+}
+
+/* register_irq_to_dma_channel
+ * - register an event with the DMA channel
+ *     mcode_ptr       the pointer to the buffer for PL330 DMASEV micro code
+ *                     to be stored into
+ *     uEventNum       the event number to be assigned to this DMA channel
+ */
+static int register_irq_to_dma_channel(u8 *mcode_ptr, int uEventNum)
+{
+       return encode_dma_send_event(mcode_ptr, (u8)uEventNum);
+}
+
+/* config_dma_set_infinite_loop
+ * - set an infinite loop
+ *     mcode_ptr       the pointer to the buffer for PL330 DMAPLPEND micro
+ *                     code to be stored into
+ *     bBwJump         the relative location of the first instruction in the
+ *                     the program loop
+ */
+static int config_dma_set_infinite_loop(u8 *mcode_ptr, int uBwJump)
+{
+       return encode_dma_loop_forever(mcode_ptr, (u8)uBwJump);
+}
+
+/* config_dma_mark_end
+ * - mark the end of the DMA request
+ *     mcode_ptr       the pointer to the buffer for PL330 DMAEND micro code
+ *                     to be stored into
+ */
+static int config_dma_mark_end(u8 *mcode_ptr)
+{
+       return encode_dma_end(mcode_ptr);
+}
+
+/* start_dma_controller
+ * - start the DMA controller
+ */
+void start_dma_controller(u32 *mbuf)
+{
+       return;
+}
+
+/* stop_dma_controller
+ * - stop the DMA controller
+ *
+ *     mbuf    the address of the buffer for DMAKILL micro code to be stored
+ */
+void stop_dma_controller(u32 *mbuf)
+{
+       encode_dma_kill_dmac_over_dbginst(mbuf);
+}
+
+/* setup_dma_channel
+ * - set up a DMA channel for the DMA operation
+ *
+ *     mbuf            the address of the buffer that will contain PL330
+ *                     D MA micro codes
+ *     dma_param       the parameter set for a DMA operation
+ *     chanNum         the DMA channel number to be started
+ */
+int setup_dma_channel(u8 *mbuf, struct DMA_parameters dma_param, int chanNum)
+{
+       int mcode_size = 0, msize = 0;
+       msize = config_dma_start_address(mbuf, dma_param.mSrcAddr);
+       mcode_size += msize;
+       msize = config_dma_destination_address(mbuf + mcode_size,
+                                               dma_param.mDstAddr);
+       mcode_size += msize;
+       msize = config_dma_control(mbuf+mcode_size, dma_param.mControl);
+       mcode_size += msize;
+       msize = config_dma_transfer_size(mbuf+mcode_size, dma_param);
+       mcode_size += msize;
+       if (dma_param.mIrqEnable) {
+               msize = register_irq_to_dma_channel(mbuf+mcode_size, chanNum);
+               mcode_size += msize;
+       }
+       if (dma_param.mLoop) {
+               msize = config_dma_set_infinite_loop(mbuf+mcode_size,
+                                       dma_param.mBwJump+mcode_size);
+               mcode_size += msize;
+       }
+       if (dma_param.mLastReq) {
+               msize = config_dma_mark_end(mbuf+mcode_size);
+               mcode_size += msize;
+       }
+       return mcode_size;
+}
+
+/* start_dma_channel
+ * - get the DMA channel started
+ * mbuf                the address of the buffer for DMAGO micro
+ *             code to be stored at
+ * chanNum     the DMA channel number to be started
+ * mbufAddr    the start address of the buffer containing
+ *             PL330 DMA micro codes
+*/
+void start_dma_channel(u32 *mbuf, int chanNum, u32 mbufAddr, int secureMode)
+{
+       encode_dma_go_over_dbginst(mbuf, (u8)chanNum, mbufAddr,
+                                                       (u8)secureMode);
+}
+
+/* stop_dma_channel
+ * - get the DMA channel stopped
+ * mbuf                the address of the buffer for DMAKILL micro code to be 
stored
+ * chanNum     the DMA channel number to be stopped
+*/
+
+void stop_dma_channel(u32 *mbuf, int chanNum)
+{
+        encode_dma_kill_channel_over_dbginst(mbuf, (u8)chanNum);
+
+}
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h 
b/arch/arm/plat-samsung/include/plat/cpu.h
index d316b4a..1f8af60 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -78,6 +78,7 @@ extern struct sysdev_class s3c2442_sysclass;
 extern struct sysdev_class s3c2443_sysclass;
 extern struct sysdev_class s3c6410_sysclass;
 extern struct sysdev_class s3c64xx_sysclass;
+extern struct sysdev_class s5p6440_sysclass;
 
 extern void (*s5pc1xx_idle)(void);
 
diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330-mcode.h 
b/arch/arm/plat-samsung/include/plat/dma-pl330-mcode.h
new file mode 100644
index 0000000..1b21477
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330-mcode.h
@@ -0,0 +1,103 @@
+/* linux/arch/arm/plat-s5p/dma-pl330-mcode.h
+ *
+ *  Copyright (c) 2010 Samsung Electronics
+ *             http://www.samsung.com/
+ *
+ * DMA PL330 microcode
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARM_PLAT_DMA_PL330_MCODE_H
+#define __ARM_PLAT_DMA_PL330_MCODE_H __FILE__
+
+#include <linux/sysdev.h>
+
+#define print_warning(fmt...)          printk(fmt)
+
+#define PL330_P2M_DMA                  0
+#define PL330_M2P_DMA                  1
+#define PL330_M2M_DMA                  2
+#define PL330_P2P_DMA                  3
+
+#define        PL330_MAX_ITERATION_NUM         256
+#define        PL330_MAX_JUMPBACK_NUM          256
+#define        PL330_MAX_EVENT_NUM             32
+#define        PL330_MAX_PERIPHERAL_NUM        32
+#define        PL330_MAX_CHANNEL_NUM           8
+
+#define DMA_DBGSTATUS                  0x0
+#define DMA_DBGCMD                     0x1
+#define DMA_DBGINST0                   0x2
+#define DMA_DBGINST1                   0x3
+
+#define DMAMOV                 (0xbc)
+#define DMALD          (0x04)
+#define DMALDS                 (0x05)
+#define DMALDB                 (0x07)
+#define DMALDPS        (0x25)
+#define DMAST          (0x08)
+#define DMASTS                 (0x09)
+#define DMASTB                 (0x0b)
+#define DMASTPS        (0x29)
+#define DMASTZ                 (0x0c)
+#define DMALP          (0x20)
+#define DMALPFE        (0x28)
+#define DMALPEND       (0x38)
+#define DMALPENDS      (0x39)
+#define DMALPENDB      (0x3b)
+#define DMAWFPS        (0x30)
+#define DMAWFPB        (0x32)
+#define DMAWFP                 (0x31)
+#define DMAFLUSHP      (0x35)
+#define DMAEND                 (0x00)
+#define DMARMB                 (0x12)
+#define DMASEV                 (0x34)
+
+#define Outp32(addr, data)             (*(u32 *)(addr) = (data))
+#define Inp32(addr)                    (*(u32 *)(addr))
+
+/* Parameter set for Channel Control Register */
+struct DMA_control{
+       unsigned        uSI;/* [0] Transfer size not count*/
+       unsigned        uSBSize;/* [3:1] Source 1 transfer size*/
+       unsigned        uSBLength;/* [7:4] Sourse burst len*/
+       unsigned        uSProt;/* [10:8] Source Protection set 101b=5*/
+       unsigned        uSCache;/* [13:11] Source Cache control*/
+       unsigned        uDI;/* [14] Destination increment*/
+       unsigned        uDBSize;/* [17:15] Destination 1 transfer size*/
+       unsigned        uDBLength;/* [21:18] Destination burst len*/
+       unsigned         uDProt;/* [24:22] Source Protection set 101b=5*/
+       unsigned        uDCache;/* [27:25] Source Cache control*/
+       unsigned        uESSize;/* [31:28] endian_swap_size     */
+};
+
+/* Parameter list for a DMA operation */
+struct DMA_parameters{
+       unsigned long           mDirection;/* DMA direction */
+       unsigned long           mPeriNum;/* DMA Peripheral number */
+       unsigned long           mSrcAddr;/* DMA source address */
+       unsigned long           mDstAddr;/* DMA destination address */
+       unsigned long           mTrSize;/* DMA Transfer size */
+       struct DMA_control      mControl;
+       unsigned long           mIrqEnable;/* DMA Send IRQ */
+       unsigned long           mLoop;  /* DMA Infinite Loop - 0(off) */
+       unsigned long           mBwJump;/* DMA backward relative offset */
+       unsigned long           mLastReq;/* The last DMA Req.  */
+};
+
+extern void start_dma_controller(u32 *mbuf);
+
+extern void stop_dma_controller(u32 *mbuf);
+
+extern int setup_dma_channel(u8 *mbuf,
+               struct DMA_parameters dma_param, int chanNum);
+
+extern void start_dma_channel(u32 *mbuf, int chanNum,
+                                       u32 mbufAddr, int secureMode);
+
+extern void stop_dma_channel(u32 *mbuf, int chanNum);
+
+#endif
diff --git a/arch/arm/plat-samsung/include/plat/dma.h 
b/arch/arm/plat-samsung/include/plat/dma.h
index 7584d75..a71897d 100644
--- a/arch/arm/plat-samsung/include/plat/dma.h
+++ b/arch/arm/plat-samsung/include/plat/dma.h
@@ -10,6 +10,61 @@
  * published by the Free Software Foundation.
 */
 
+
+/* types */
+#ifndef __ARM_PLAT_SAMSUNG_DMA_H
+#define __ARM_PLAT_SAMSUNG_DMA_H
+
+enum s3c2410_dma_state {
+       S3C2410_DMA_IDLE,
+       S3C2410_DMA_RUNNING,
+       S3C2410_DMA_PAUSED
+};
+
+/* enum s3c2410_dma_loadst
+ *
+ * This represents the state of the DMA engine, wrt to the loaded / running
+ * transfers. Since we don't have any way of knowing exactly the state of
+ * the DMA transfers, we need to know the state to make decisions on wether
+ * we can
+ *
+ * S3C2410_DMA_NONE
+ *
+ * There are no buffers loaded (the channel should be inactive)
+ *
+ * S3C2410_DMA_1LOADED
+ *
+ * There is one buffer loaded, however it has not been confirmed to be
+ * loaded by the DMA engine. This may be because the channel is not
+ * yet running, or the DMA driver decided that it was too costly to
+ * sit and wait for it to happen.
+ *
+ * S3C2410_DMA_1RUNNING
+ *
+ * The buffer has been confirmed running, and not finisged
+ *
+ * S3C2410_DMA_1LOADED_1RUNNING
+ *
+ * There is a buffer waiting to be loaded by the DMA engine, and one
+ * currently running.
+*/
+
+
+enum s3c2410_dma_loadst {
+       S3C2410_DMALOAD_NONE,
+       S3C2410_DMALOAD_1LOADED,
+       S3C2410_DMALOAD_1RUNNING,
+       S3C2410_DMALOAD_1LOADED_1RUNNING,
+};
+
+struct s3c2410_dma_stats {
+       unsigned long           loads;
+       unsigned long           timeout_longest;
+       unsigned long           timeout_shortest;
+       unsigned long           timeout_avg;
+       unsigned long           timeout_failed;
+};
+
 enum s3c2410_dma_buffresult {
        S3C2410_RES_OK,
        S3C2410_RES_ERR,
@@ -56,7 +111,6 @@ typedef int  (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
                                   enum s3c2410_chan_op );
 
 
-
 /* s3c2410_dma_request
  *
  * request a dma channel exclusivley
@@ -120,8 +174,7 @@ extern int s3c2410_dma_devconfig(int channel, enum 
s3c2410_dmasrc source,
 
 extern int s3c2410_dma_getposition(unsigned int channel,
                                   dma_addr_t *src, dma_addr_t *dest);
-
 extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn);
 extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn);
 
-
+#endif
-- 
1.6.6

--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to