OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [cortexm/] [a2fxxx/] [var/] [current/] [src/] [hal_dma.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/*==========================================================================
2
//
3
//      hal_dma.c
4
//
5
//      Cortex-M Actel A2F DMA channels configuration
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 2011 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later
16
// version.
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21
// for more details.
22
//
23
// You should have received a copy of the GNU General Public License
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26
//
27
// As a special exception, if other files instantiate templates or use
28
// macros or inline functions from this file, or you compile this file
29
// and link it with other works to produce a work based on this file,
30
// this file does not by itself cause the resulting work to be covered by
31
// the GNU General Public License. However the source code for this file
32
// must still be made available in accordance with section (3) of the GNU
33
// General Public License v2.
34
//
35
// This exception does not invalidate any other reasons why a work based
36
// on this file might be covered by the GNU General Public License.
37
// -------------------------------------------
38
// ####ECOSGPLCOPYRIGHTEND####
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    ccoutand
43
// Contributors:
44
// Date:         2011-02-03
45
// Description:
46
//
47
//####DESCRIPTIONEND####
48
//
49
//========================================================================*/
50
 
51
#include <pkgconf/hal.h>
52
#include <pkgconf/hal_cortexm.h>
53
#include <pkgconf/hal_cortexm_a2fxxx.h>
54
#ifdef CYGPKG_KERNEL
55
#include <pkgconf/kernel.h>
56
#endif
57
 
58
#include <cyg/infra/diag.h>
59
#include <cyg/infra/cyg_type.h>
60
#include <cyg/infra/cyg_trac.h>         // tracing macros
61
#include <cyg/infra/cyg_ass.h>          // assertion macros
62
 
63
#include <cyg/hal/hal_arch.h>           // HAL header
64
#include <cyg/hal/hal_intr.h>           // HAL header
65
#include <cyg/hal/hal_if.h>             // HAL header
66
#include <cyg/hal/drv_api.h>
67
 
68
#ifdef CYGDBG_HAL_CORTEXM_A2FXXX_DMA_TRACE
69
# define DMA_TRACE(args...) diag_printf(args)
70
#else
71
# define DMA_TRACE(args...)
72
#endif
73
 
74
//-----------------------------------------------------------------------------
75
// DMA channel ISR/DSR handling
76
 
77
typedef struct a2fxxx_dma_ch {
78
    cyg_ISR_t*      isr;
79
    cyg_DSR_t*      dsr;
80
    cyg_addrword_t  data;
81
} a2fxxx_dma_ch;
82
 
83
typedef struct a2fxxx_dma_info {
84
    cyg_uint32      init;
85
    cyg_uint32      base;
86
    cyg_handle_t    interrupt_handle;
87
    cyg_interrupt   interrupt_data;
88
    a2fxxx_dma_ch   ch[CYGHWR_HAL_A2FXXX_DMA_MAX_CHANNEL];
89
    cyg_uint32      dma_cr[CYGHWR_HAL_A2FXXX_DMA_MAX_CHANNEL];
90
    cyg_uint32      dma_sr;
91
} a2fxxx_dma_info;
92
 
93
static a2fxxx_dma_info a2fxxx_dma = {
94
    .base = CYGHWR_HAL_A2FXXX_DMA,
95
    .init =0,
96
};
97
 
98
 
99
//-----------------------------------------------------------------------------
100
// DMA ISR handler
101
 
102
static cyg_uint32
103
a2fxxx_dma_isr (cyg_vector_t vector, cyg_addrword_t data)
104
{
105
    a2fxxx_dma_info *dma = (a2fxxx_dma_info *) data;
106
    cyg_uint32 res = 0, sr = 0;
107
    cyg_uint8 i = 0, j = 0;
108
 
109
    HAL_READ_UINT32(dma->base + CYGHWR_HAL_A2FXXX_DMA_BUFFER_STATUS, sr);
110
    dma->dma_sr |= sr;
111
 
112
    DMA_TRACE("DMA interrupt, sr 0x%x\n", dma->dma_sr);
113
 
114
    while(i < 16){
115
        if( sr & 0x1 ){
116
            j = i >> 1;
117
            if(dma->ch[j].isr != NULL){
118
                res = dma->ch[j].isr(i, dma->ch[j].data);
119
            }
120
        }
121
        sr = sr >> 1; i++;
122
    }
123
    cyg_drv_interrupt_acknowledge (CYGNUM_HAL_INTERRUPT_DMA);
124
    cyg_drv_interrupt_mask (CYGNUM_HAL_INTERRUPT_DMA);
125
    return (CYG_ISR_CALL_DSR | CYG_ISR_HANDLED);
126
}
127
 
128
 
129
//-----------------------------------------------------------------------------
130
// DMA DSR handler
131
 
132
static void
133
a2fxxx_dma_dsr (cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
134
{
135
    a2fxxx_dma_info *dma = (a2fxxx_dma_info *) data;
136
    cyg_uint8 i = 0, j = 0;
137
    cyg_uint32 sr;
138
 
139
    cyg_drv_isr_lock ();
140
    sr = dma->dma_sr;
141
    dma->dma_sr = 0;
142
    cyg_drv_isr_unlock ();
143
 
144
    while(i < 16){
145
        if( sr & 0x1 ){
146
            j = i >> 1;
147
            if(dma->ch[j].dsr != NULL){
148
                dma->ch[j].dsr(i, 0, dma->ch[j].data);
149
            }
150
        }
151
        sr = sr >> 1; i++;
152
    }
153
 
154
    cyg_drv_interrupt_unmask (CYGNUM_HAL_INTERRUPT_DMA);
155
}
156
 
157
 
158
//-----------------------------------------------------------------------------
159
// DMA Initialization
160
 
161
void
162
hal_dma_init( void )
163
{
164
    cyg_uint8 i = 0;
165
 
166
    // Avoid multiple initialization
167
    if(a2fxxx_dma.init)
168
        return;
169
 
170
    a2fxxx_dma.init = 1;
171
 
172
    // Reset DMA
173
    CYGHWR_HAL_A2FXXX_PERIPH_RESET( CYGHWR_HAL_A2FXXX_PERIPH_SOFTRST(PDMA) );
174
 
175
    // Clear channel ISR / DSR
176
    while( i < CYGHWR_HAL_A2FXXX_DMA_MAX_CHANNEL ) {
177
        a2fxxx_dma.ch[i].isr    = NULL;
178
        a2fxxx_dma.ch[i].dsr    = NULL;
179
        a2fxxx_dma.dma_cr[i]    = 0;
180
        a2fxxx_dma.ch[i++].data = 0;
181
    }
182
    a2fxxx_dma.dma_sr = 0;
183
 
184
    // Register DMA interrupt
185
    cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_DMA,
186
                           CYGNUM_HAL_CORTEXM_A2FXXX_DMA_ISR_PRIORITY,
187
                           (cyg_addrword_t)&a2fxxx_dma,
188
                           &a2fxxx_dma_isr,
189
                           &a2fxxx_dma_dsr,
190
                           &(a2fxxx_dma.interrupt_handle),
191
                           &(a2fxxx_dma.interrupt_data));
192
    cyg_drv_interrupt_attach(a2fxxx_dma.interrupt_handle);
193
    cyg_drv_interrupt_acknowledge (CYGNUM_HAL_INTERRUPT_DMA);
194
    cyg_drv_interrupt_unmask (CYGNUM_HAL_INTERRUPT_DMA);
195
 
196
    // Release DMA
197
    CYGHWR_HAL_A2FXXX_PERIPH_RELEASE( CYGHWR_HAL_A2FXXX_PERIPH_SOFTRST(PDMA) );
198
 
199
    // HW initialization
200
    i=0;
201
    while( i < CYGHWR_HAL_A2FXXX_DMA_MAX_CHANNEL ) {
202
        HAL_WRITE_UINT32(a2fxxx_dma.base + CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL(i++),
203
                         CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_RESET);
204
    }
205
}
206
 
207
 
208
//-----------------------------------------------------------------------------
209
// Register the DMA sub-channel ISR / DSR
210
 
211
__externC cyg_uint32
212
a2fxxx_dma_ch_attach(cyg_uint8 ch, cyg_ISR_t *isr, cyg_DSR_t *dsr,
213
                     cyg_addrword_t data)
214
{
215
    cyg_uint32 res = 1;
216
 
217
    CYG_ASSERT (ch < CYGHWR_HAL_A2FXXX_DMA_MAX_CHANNEL,
218
                         "DMA : Channel number out of range (Attach).");
219
 
220
#ifdef CYGPKG_KERNEL
221
    cyg_interrupt_disable();
222
#endif
223
    if( a2fxxx_dma.ch[ch].isr != NULL ||
224
        a2fxxx_dma.ch[ch].dsr != NULL || a2fxxx_dma.ch[ch].data != 0 ) {
225
        res = 0;
226
    } else {
227
        a2fxxx_dma.ch[ch].isr  = isr;
228
        a2fxxx_dma.ch[ch].dsr  = dsr;
229
        a2fxxx_dma.ch[ch].data = data;
230
    }
231
#ifdef CYGPKG_KERNEL
232
    cyg_interrupt_enable();
233
#endif
234
 
235
    return res;
236
}
237
 
238
 
239
//-----------------------------------------------------------------------------
240
// Update DMA source / destination address increment
241
 
242
__externC void
243
a2fxxx_dma_update_incr(cyg_uint8 ch, cyg_bool dst, cyg_uint8 incr)
244
{
245
    CYG_ASSERT (ch < CYGHWR_HAL_A2FXXX_DMA_MAX_CHANNEL,
246
                          "DMA : Channel number out of range (Update).");
247
 
248
    if(dst==false){
249
        // Clear bits
250
        a2fxxx_dma.dma_cr[ch] &= ~CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_SRC_INCR_4B;
251
        a2fxxx_dma.dma_cr[ch] |= CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_SRC_INCR(incr);
252
    }
253
    else {
254
        // Clear bits
255
        a2fxxx_dma.dma_cr[ch] &= ~CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_DST_INCR_4B;
256
        a2fxxx_dma.dma_cr[ch] |= CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_DST_INCR(incr);
257
    }
258
}
259
 
260
 
261
//-----------------------------------------------------------------------------
262
// Setup DMA channel
263
//
264
// channel      select the DMA channel ID.
265
// type         select the transfer type to be performed. For valid
266
//              values, check CYGHWR_HAL_A2FXXX_DMA_XFER(_x) in var_io.h.
267
// outbound     set to true for transfer out of memory, false for transfer to
268
//              memory
269
// src_incr     select the memory address increment step for the source. Valid
270
//              values are 0, 1, 2 and 4 byte(s). 0 can be used for DMA
271
//              transfer from peripheral FIFO for instance.
272
// dst_incr     select the memory address increment step for the destination.
273
//              Valid values are 0, 1, 2 and 4 byte(s). 0 can be used for DMA
274
//              transfer to peripheral FIFO for instance.
275
// pri          select the DMA channel priority (true = high , false = low)
276
// wr_adj       indicates the number of FCLK periods which the PDMA must wait
277
//              after completion of a read or write access to a peripheral before
278
//              evaluating the out-of-band status signals from that peripheral
279
//              for another transfer
280
 
281
__externC cyg_uint32
282
a2fxxx_dma_ch_setup(cyg_uint8 ch, cyg_uint8 type, cyg_bool outbound,
283
      cyg_uint8 src_incr, cyg_uint8 dst_incr, cyg_bool pri, cyg_uint8 wr_adj)
284
{
285
    cyg_uint32 res = 1;
286
    cyg_uint32 xfer_type = 0, xfer_dir = 0, xfer_incr =
287
                                    CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_XFER_BYTE;
288
    a2fxxx_dma.dma_cr[ch] = 0;
289
 
290
    CYG_ASSERT (ch < CYGHWR_HAL_A2FXXX_DMA_MAX_CHANNEL,
291
                               "DMA : Channel number out of range (Setup).");
292
 
293
    DMA_TRACE("DMA setup channel %d, direction: %s, type %x, step %d-%d byte(s)\n", ch ,
294
             ((outbound==true) ? "outbound" : "inbound"), type, src_incr, dst_incr );
295
 
296
    if( type != CYGHWR_HAL_A2FXXX_DMA_XFER_MEMORY ){
297
        xfer_type = CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_PERIPH_SEL(type) |
298
                CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_PERIPH;
299
    }
300
 
301
    if( outbound == true ){
302
        xfer_dir = CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_DIR;
303
    }
304
 
305
    a2fxxx_dma_update_incr(ch, true, dst_incr);
306
    a2fxxx_dma_update_incr(ch, false, src_incr);
307
 
308
    a2fxxx_dma.dma_cr[ch] |= ( xfer_type | xfer_dir |
309
          ((pri == true) ? CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_CLR_HI_PRI : 0) |
310
          CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_CLR_COMPA |
311
          CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_CLR_COMPB |
312
          CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_WR_ADJ(wr_adj) |
313
          xfer_incr);
314
 
315
    HAL_WRITE_UINT32(a2fxxx_dma.base + CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL(ch),
316
                                    a2fxxx_dma.dma_cr[ch]);
317
 
318
    return res;
319
}
320
 
321
 
322
//-----------------------------------------------------------------------------
323
// Remove DMA channel handler
324
 
325
__externC void
326
a2fxxx_dma_ch_detach (cyg_uint8 ch)
327
{
328
    CYG_ASSERT (ch < CYGHWR_HAL_A2FXXX_DMA_MAX_CHANNEL,
329
                              "DMA : Channel number out of range (Detach).");
330
 
331
#ifdef CYGPKG_KERNEL
332
    cyg_interrupt_disable();
333
#endif
334
    a2fxxx_dma.ch[ch].isr  = NULL;
335
    a2fxxx_dma.ch[ch].dsr  = NULL;
336
    a2fxxx_dma.ch[ch].data = 0;
337
#ifdef CYGPKG_KERNEL
338
    cyg_interrupt_enable();
339
#endif
340
}
341
 
342
 
343
//-----------------------------------------------------------------------------
344
// Start DMA transfer
345
 
346
__externC cyg_uint32
347
a2fxxx_dma_xfer (cyg_uint8 ch, cyg_bool polled, cyg_uint32 len, cyg_uint8 *src,
348
                     cyg_uint8 *dst)
349
{
350
    cyg_uint32 res = 1;
351
    cyg_uint32 src_reg, dst_reg, cnt_reg;
352
    cyg_uint32 sub = 0;
353
    cyg_haladdress dma_src = (cyg_haladdress) src;
354
    cyg_haladdress dma_dst = (cyg_haladdress) dst;
355
 
356
    CYG_ASSERT (ch < CYGHWR_HAL_A2FXXX_DMA_MAX_CHANNEL,
357
                           "DMA : Channel number out of range (Transfer).");
358
 
359
    if( polled == true )
360
        a2fxxx_dma.dma_cr[ch] &= ~CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_INTEN;
361
    else
362
        a2fxxx_dma.dma_cr[ch] |= CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_INTEN;
363
 
364
    HAL_WRITE_UINT32(a2fxxx_dma.base + CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL(ch),
365
                                 a2fxxx_dma.dma_cr[ch]);
366
 
367
    HAL_READ_UINT32(a2fxxx_dma.base + CYGHWR_HAL_A2FXXX_DMA_CHx_STATUS(ch), sub);
368
    sub = CYGHWR_HAL_A2FXXX_DMA_GET_SUB_ID( sub );
369
 
370
    src_reg = ((sub == 0) ? CYGHWR_HAL_A2FXXX_DMA_CHx_BA_SRC(ch) :
371
                            CYGHWR_HAL_A2FXXX_DMA_CHx_BB_SRC(ch));
372
    dst_reg = ((sub == 0) ? CYGHWR_HAL_A2FXXX_DMA_CHx_BA_DST(ch) :
373
                            CYGHWR_HAL_A2FXXX_DMA_CHx_BB_DST(ch));
374
    cnt_reg = ((sub == 0) ? CYGHWR_HAL_A2FXXX_DMA_CHx_BA_COUNT(ch) :
375
                            CYGHWR_HAL_A2FXXX_DMA_CHx_BB_COUNT(ch));
376
 
377
    DMA_TRACE("DMA transfer of length %d on channel %d(%s) - SRC: 0x%x / DST: 0x%x\n",
378
                          len, ch, ((sub==0) ? "A" : "B"), dma_src, dma_dst);
379
    DMA_TRACE("DMA register address 0x%x / 0x%x\n", src_reg , dst_reg);
380
 
381
    HAL_WRITE_UINT32(a2fxxx_dma.base + src_reg, dma_src);
382
    HAL_WRITE_UINT32(a2fxxx_dma.base + dst_reg, dma_dst);
383
    HAL_WRITE_UINT32(a2fxxx_dma.base + cnt_reg, len);
384
 
385
    return res;
386
}
387
 
388
 
389
//-----------------------------------------------------------------------------
390
// Clear DMA interrupt
391
 
392
void a2fxxx_dma_clear_interrupt (cyg_uint8 ch)
393
{
394
    cyg_uint32 reg;
395
 
396
    CYG_ASSERT (ch < CYGHWR_HAL_A2FXXX_DMA_MAX_CHANNEL,
397
                           "DMA : Channel number out of range (Clear IRQ).");
398
 
399
    DMA_TRACE("DMA status register 0x%x\n",
400
                     (a2fxxx_dma.base + CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL(ch)));
401
 
402
    HAL_READ_UINT32(a2fxxx_dma.base + CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL(ch), reg);
403
    reg |= (CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_CLR_COMPA |
404
            CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL_CLR_COMPB);
405
    HAL_WRITE_UINT32(a2fxxx_dma.base + CYGHWR_HAL_A2FXXX_DMA_CHx_CTRL(ch), reg);
406
}
407
 
408
 
409
//-----------------------------------------------------------------------------
410
// Clear DMA interrupt
411
 
412
cyg_uint8 a2fxxx_dma_get_comp_flag (cyg_uint8 ch)
413
{
414
    cyg_uint32 reg;
415
 
416
    CYG_ASSERT (ch < CYGHWR_HAL_A2FXXX_DMA_MAX_CHANNEL,
417
                                  "DMA : Channel number out of range (Get).");
418
 
419
    HAL_READ_UINT32(a2fxxx_dma.base + CYGHWR_HAL_A2FXXX_DMA_CHx_STATUS(ch), reg);
420
 
421
    return (reg&0x3);
422
}
423
 
424
//-----------------------------------------------------------------------------
425
// End of hal_dma.c

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.