4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2011 Develer S.r.l. (http://www.develer.com/)
32 * \brief HSMCI driver implementation.
34 * \author Daniele Basile <asterix@develer.com>
37 #include "dmac_sam3.h"
38 #include <drv/irq_cm3.h>
41 #include <cpu/power.h>
45 #include <mware/event.h>
59 #define DMAC_CHANNEL_CNT 5
60 struct DmacCh dmac_ch[] =
67 .ctrla = &DMAC_CTRLA0,
68 .ctrlb = &DMAC_CTRLB0,
75 .ctrla = &DMAC_CTRLA1,
76 .ctrlb = &DMAC_CTRLB1,
83 .ctrla = &DMAC_CTRLA2,
84 .ctrlb = &DMAC_CTRLB2,
91 .ctrla = &DMAC_CTRLA3,
92 .ctrlb = &DMAC_CTRLB3,
99 .ctrla = &DMAC_CTRLA4,
100 .ctrlb = &DMAC_CTRLB4,
107 .ctrla = &DMAC_CTRLA5,
108 .ctrlb = &DMAC_CTRLB5,
113 /* We use event to signal the end of conversion */
114 static Event data_ready;
115 static Dmac dmac[DMAC_CHANNEL_CNT];
116 static uint8_t dmac_ch_enabled;
118 void dmac_setSourcesLLI(int ch, DmacDesc *lli, uint32_t src, uint32_t dst, uint32_t desc)
125 lli->dsc_addr = desc;
128 void dmac_configureDmacLLI(int ch, DmacDesc *lli, size_t transfer_size, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb)
132 *dmac_ch[ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT);
133 lli->ctrla = ctrla | (transfer_size & DMAC_CTRLA_BTSIZE_MASK);
134 lli->ctrlb = ctrlb & ~BV(DMAC_CTRLB_IEN);
135 *dmac_ch[ch].desc = (uint32_t)lli;
138 void dmac_setSources(int ch, uint32_t src, uint32_t dst)
142 *dmac_ch[ch].src = src;
143 *dmac_ch[ch].dst = dst;
144 *dmac_ch[ch].desc = 0;
147 void dmac_configureDmac(int ch, size_t transfer_size, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb)
151 *dmac_ch[ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT) | BV(DMAC_CFG_SOD);
152 *dmac_ch[ch].ctrla = ctrla | (transfer_size & DMAC_CTRLA_BTSIZE_MASK);
153 *dmac_ch[ch].ctrlb = ctrlb & ~BV(DMAC_CTRLB_IEN);
156 int dmac_start(int ch)
158 if (DMAC_CHSR & BV(ch))
160 dmac[ch].errors |= DMAC_ERR_CH_ALREDY_ON;
167 int dmac_stop(int ch)
173 bool dmac_isLLIDone(int ch)
175 return (DMAC_EBCIMR |= (BV(ch) << DMAC_EBCISR_CBTC0));
178 bool dmac_waitLLIDone(int ch)
180 while(!(DMAC_EBCIMR |= (BV(ch) << DMAC_EBCISR_CBTC0)))
187 bool dmac_isDone(int ch)
189 //event_wait(&data_ready);
190 return (*dmac_ch[ch].ctrla & BV(31));//(DMAC_CHSR |= (BV(dmac->ch) << DMAC_CHSR_EMPT0));
193 bool dmac_waitDone(int ch)
195 event_wait(&data_ready);
200 int dmac_error(int ch)
202 uint32_t err = ((DMAC_EBCISR & 0x3F0000) | dmac[ch].errors);
207 static DECLARE_ISR(dmac_irq)
209 uint32_t status = DMAC_EBCISR;
210 uint32_t irq_ch = (status & dmac_ch_enabled) & 0xFF;
211 //kprintf(" %08lx %08lx\n", status, irq_ch);
213 for(int i = 0; i < 8; i++)
220 irq_ch = (status & (dmac_ch_enabled << DMAC_EBCIDR_CBTC0)) >> DMAC_EBCIDR_CBTC0;
221 //kprintf("c %08lx %08lx\n", status, irq_ch);
223 for(int i = 0; i < 8; i++)
233 bool dmac_enableCh(int ch, dmac_handler_t handler)
235 ASSERT(ch <= DMAC_CHANNEL_CNT);
237 dmac_ch_enabled |= BV(ch);
240 dmac[ch].handler = handler;
241 DMAC_EBCIER |= (BV(ch) << DMAC_EBCIER_BTC0) | (BV(ch) << DMAC_EBCIDR_CBTC0);
242 kprintf("Init dmac ch[%08lx]\n", DMAC_EBCIMR);
251 memset(&dmac, 0, sizeof(dmac));
254 DMAC_EBCIDR = 0x3FFFFF;
257 pmc_periphEnable(DMAC_ID);
258 DMAC_EN = BV(DMAC_EN_ENABLE);
260 sysirq_setHandler(INT_DMAC, dmac_irq);