Clean up the code, remove unneed status flag.
[bertos.git] / bertos / cpu / cortex-m3 / drv / dmac_sam3.c
index 21045b7f89e47f3979a216bbe773cd127b632544..e97066860e792f27b7a6f0d882f0ea3a0a075ca0 100644 (file)
  */
 
 #include "dmac_sam3.h"
-
-#include "hsmci_sam3.h"
-#include "hw/hw_sd.h"
-
-#include <drv/timer.h>
 #include <drv/irq_cm3.h>
 
 #include <cpu/irq.h>
 
 #include <io/cm3.h>
 
+#include <mware/event.h>
+
+#include <string.h>
+
 struct DmacCh
 {
        reg32_t *src;
@@ -57,7 +56,7 @@ struct DmacCh
        reg32_t *ctrlb;
 };
 
-#define DMAC_CHANNEL_CNT   5
+#define DMAC_CHANNEL_CNT   6
 struct DmacCh dmac_ch[] =
 {
        {
@@ -110,65 +109,97 @@ struct DmacCh dmac_ch[] =
        },
 };
 
-void dmac_setSources(Dmac *dmac, uint8_t ch, uint32_t src, uint32_t dst, size_t transfer_size)
+/* We use event to signal the end of conversion */
+static Dmac dmac[DMAC_CHANNEL_CNT];
+static uint8_t dmac_ch_enabled;
+
+void dmac_setLLITransfer(int ch, DmacDesc *lli, uint32_t cfg)
 {
-       ASSERT(ch <= DMAC_CHANNEL_CNT);
+       DMAC_CHDR = BV(ch);
+       reg32_t reg = DMAC_EBCISR;
+       (void)reg;
 
+       *dmac_ch[ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT);
+       *dmac_ch[ch].desc = (uint32_t)lli;
+}
+
+void dmac_setSources(int ch, uint32_t src, uint32_t dst)
+{
        DMAC_CHDR = BV(ch);
 
        *dmac_ch[ch].src = src;
        *dmac_ch[ch].dst = dst;
        *dmac_ch[ch].desc = 0;
-       dmac->transfer_size = transfer_size;
 }
 
-void dmac_configureDmac(Dmac *dmac, uint8_t ch, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb)
+void dmac_configureDmac(int ch, size_t transfer_size, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb)
 {
-       ASSERT(ch <= DMAC_CHANNEL_CNT);
-
        DMAC_CHDR = BV(ch);
 
-       *dmac_ch[ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT);
-       *dmac_ch[ch].ctrla = ctrla | (dmac->transfer_size & DMAC_CTRLA_BTSIZE_MASK);
-       *dmac_ch[ch].ctrlb = ctrlb BV(DMAC_CTRLB_IEN);
+       *dmac_ch[ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT) | BV(DMAC_CFG_SOD);
+       *dmac_ch[ch].ctrla = ctrla | (transfer_size & DMAC_CTRLA_BTSIZE_MASK);
+       *dmac_ch[ch].ctrlb = ctrlb & ~BV(DMAC_CTRLB_IEN);
 }
 
-int dmac_start(Dmac *dmac, uint8_t ch)
+int dmac_start(int ch)
 {
-       ASSERT(ch <= DMAC_CHANNEL_CNT);
-
        if (DMAC_CHSR & BV(ch))
        {
-               dmac->errors |= DMAC_ERR_CH_ALREDY_ON;
+               dmac[ch].errors |= DMAC_ERR_CH_ALREDY_ON;
                return -1;
        }
-
        DMAC_CHER = BV(ch);
+       dmac_ch_enabled |= BV(ch);
        return 0;
 }
 
-bool dmac_isDone(Dmac *dmac, uint8_t ch)
+void dmac_stop(int ch)
 {
-       (void)dmac;
-       return (DMAC_EBCISR |= BV(ch));
+       DMAC_CHDR = BV(ch);
+       dmac_ch_enabled &= ~BV(ch);
 }
 
-bool dmac_waitDone(Dmac *dmac, uint8_t ch)
+int dmac_error(int ch)
 {
-       (void)dmac;
-       while(!(DMAC_EBCISR |= BV(ch)))
-               cpu_relax();
-
-       return true;
+       uint32_t err = ((DMAC_EBCISR & 0x3F0000) | dmac[ch].errors);
+       dmac[ch].errors = 0;
+       return err;
 }
 
 static DECLARE_ISR(dmac_irq)
 {
+       uint32_t status = DMAC_EBCISR;
+       uint32_t irq_ch = (status & (((dmac_ch_enabled |
+                                                               (dmac_ch_enabled << DMAC_EBCIDR_ERR0) >> DMAC_EBCIDR_ERR0) |
+                                                               (dmac_ch_enabled << DMAC_EBCIDR_CBTC0) >> DMAC_EBCIDR_CBTC0) & 0xFF));
+       if (irq_ch)
+               for(int i = 0; i < 6; i++)
+               {
+                       if (BV(i) & irq_ch)
+                               if(dmac[i].handler)
+                                       dmac[i].handler(status);
+               }
 }
 
-void dmac_init(Dmac *dmac)
+bool dmac_enableCh(int ch, dmac_handler_t handler)
 {
-       (void)dmac;
+       ASSERT(ch <= DMAC_CHANNEL_CNT);
+
+       dmac_ch_enabled |= BV(ch);
+       if (handler)
+       {
+               dmac[ch].handler = handler;
+               DMAC_EBCIER |= (BV(ch) << DMAC_EBCIER_BTC0) | (BV(ch) << DMAC_EBCIDR_CBTC0) | (BV(ch) << DMAC_EBCIDR_ERR0);
+               kprintf("Init dmac ch[%08lx]\n", DMAC_EBCIMR);
+       }
+
+       return true;
+}
+
+void dmac_init(void)
+{
+       dmac_ch_enabled = 0;
+       memset(&dmac, 0, sizeof(dmac));
 
        //init DMAC
        DMAC_EBCIDR = 0x3FFFFF;
@@ -176,5 +207,6 @@ void dmac_init(Dmac *dmac)
 
        pmc_periphEnable(DMAC_ID);
        DMAC_EN = BV(DMAC_EN_ENABLE);
+
        sysirq_setHandler(INT_DMAC, dmac_irq);
 }