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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [CORTEX_AT91SAM3U256_IAR/] [AT91Lib/] [peripherals/] [mci/] [mci_hs.c] - Blame information for rev 609

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 580 jeremybenn
/* ----------------------------------------------------------------------------
2
 *         ATMEL Microcontroller Software Support
3
 * ----------------------------------------------------------------------------
4
 * Copyright (c) 2008, Atmel Corporation
5
 *
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions are met:
10
 *
11
 * - Redistributions of source code must retain the above copyright notice,
12
 * this list of conditions and the disclaimer below.
13
 *
14
 * Atmel's name may not be used to endorse or promote products derived from
15
 * this software without specific prior written permission.
16
 *
17
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20
 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 * ----------------------------------------------------------------------------
28
 */
29
 
30
//------------------------------------------------------------------------------
31
//         Headers
32
//------------------------------------------------------------------------------
33
 
34
#include "mci_hs.h"
35
#include <utility/assert.h>
36
#include <utility/trace.h>
37
 
38
#include <dmad/dmad.h>
39
#include <dma/dma.h>
40
 
41
//------------------------------------------------------------------------------
42
//         Local constants
43
//------------------------------------------------------------------------------
44
 
45
/// Bit mask for status register errors.
46
#define STATUS_ERRORS (AT91C_MCI_UNRE  \
47
                       | AT91C_MCI_OVRE \
48
                       | AT91C_MCI_BLKOVRE \
49
                       | AT91C_MCI_CSTOE \
50
                       | AT91C_MCI_DTOE \
51
                       | AT91C_MCI_DCRCE \
52
                       | AT91C_MCI_RTOE \
53
                       | AT91C_MCI_RENDE \
54
                       | AT91C_MCI_RCRCE \
55
                       | AT91C_MCI_RDIRE \
56
                       | AT91C_MCI_RINDE)
57
 
58
#define STATUS_ERRORS_RESP (AT91C_MCI_CSTOE \
59
                            | AT91C_MCI_RTOE \
60
                            | AT91C_MCI_RENDE \
61
                            | AT91C_MCI_RCRCE \
62
                            | AT91C_MCI_RDIRE \
63
                            | AT91C_MCI_RINDE)
64
 
65
#define STATUS_ERRORS_DATA (AT91C_MCI_UNRE \
66
                            | AT91C_MCI_OVRE \
67
                            | AT91C_MCI_BLKOVRE \
68
                            | AT91C_MCI_CSTOE \
69
                            | AT91C_MCI_DTOE \
70
                            | AT91C_MCI_DCRCE)
71
 
72
 
73
/// MCI data timeout configuration with 1048576 MCK cycles between 2 data transfers.
74
#define DTOR_1MEGA_CYCLES           (AT91C_MCI_DTOCYC | AT91C_MCI_DTOMUL)
75
 
76
/// MCI MR: disable MCI Clock when FIFO is full
77
#ifndef AT91C_MCI_WRPROOF
78
    #define AT91C_MCI_WRPROOF 0
79
#endif
80
#ifndef AT91C_MCI_RDPROOF
81
    #define AT91C_MCI_RDPROOF 0
82
#endif
83
 
84
#define SDCARD_APP_OP_COND_CMD      (41 | AT91C_MCI_SPCMD_NONE  | AT91C_MCI_RSPTYP_48   | AT91C_MCI_TRCMD_NO )
85
#define MMC_SEND_OP_COND_CMD        (1  | AT91C_MCI_TRCMD_NO    | AT91C_MCI_SPCMD_NONE  | AT91C_MCI_RSPTYP_48 | AT91C_MCI_OPDCMD)
86
 
87
 
88
#define DISABLE    0    // Disable MCI interface
89
#define ENABLE     1    // Enable MCI interface
90
 
91
 
92
//------------------------------------------------------------------------------
93
//         Local macros
94
//------------------------------------------------------------------------------
95
 
96
/// Used to write in PMC registers.
97
#define WRITE_PMC(pPmc, regName, value)     pPmc->regName = (value)
98
 
99
/// Used to write in MCI registers.
100
#define WRITE_MCI(pMci, regName, value)     pMci->regName = (value)
101
 
102
/// Used to read from MCI registers.
103
#define READ_MCI(pMci, regName)             (pMci->regName)
104
 
105
/// Enable MCI Clock
106
#define MCICK_ENABLE(pMciHw)      WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIEN)
107
 
108
/// Disable MCI Clock
109
#define MCICK_DISABLE(pMciHw)     WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS)
110
 
111
 
112
//------------------------------------------------------------------------------
113
//         Local variables
114
//------------------------------------------------------------------------------
115
 
116
//------------------------------------------------------------------------------
117
//         Internal Functions
118
//------------------------------------------------------------------------------
119
#if defined(MCI_DMA_ENABLE)
120
#define FIFO_SIZE (0x4000 - 0x200)
121
static DmaLinkList  LLI_CH [4];
122
#define     LAST_ROW            0x100
123
static void AT91F_Prepare_Multiple_Transfer(unsigned int Channel,
124
                                            unsigned int LLI_rownumber,
125
                                            unsigned int LLI_Last_Row,
126
                                            unsigned int From_add,
127
                                            unsigned int To_add,
128
                                            unsigned int Ctrla,
129
                                            unsigned int Ctrlb)
130
{
131
    LLI_CH[LLI_rownumber].sourceAddress =  From_add;
132
    LLI_CH[LLI_rownumber].destAddress =  To_add;
133
    LLI_CH[LLI_rownumber].controlA =  Ctrla;
134
    LLI_CH[LLI_rownumber].controlB =  Ctrlb;
135
    if (LLI_Last_Row != LAST_ROW)
136
        LLI_CH[LLI_rownumber].descriptor =
137
             (unsigned int)&LLI_CH[LLI_rownumber + 1] + 0;
138
    else
139
        LLI_CH[LLI_rownumber].descriptor = 0;
140
}
141
 
142
static unsigned int DMACH_MCI_P2M(unsigned int channel_index,
143
                                  unsigned int* src_addr,
144
                                  unsigned int* dest_addr,
145
                                  unsigned int trans_size,
146
                                  unsigned char fifoForP)
147
{
148
    unsigned int srcAddress;
149
    unsigned int destAddress;
150
    unsigned int buffSize;
151
    unsigned int LLI_rownumber = 0;
152
    unsigned int srcAddressMode = fifoForP ?
153
                                  (AT91C_HDMA_SRC_ADDRESS_MODE_INCR)
154
                                : (AT91C_HDMA_SRC_ADDRESS_MODE_FIXED);
155
 
156
    // Disable dma channel
157
    DMA_DisableChannel(channel_index);
158
 
159
    // DMA channel configuration
160
    srcAddress  = (unsigned int)src_addr;    // Set the data start address
161
    destAddress = (unsigned int)dest_addr; //(unsigned int)SSC_THR_ADD; 
162
    buffSize    = trans_size;
163
 
164
    if(buffSize >= 0x10000){
165
        buffSize = 0xffff;
166
    }
167
 
168
    // Set DMA channel source address
169
    DMA_SetSourceAddr(channel_index, srcAddress);
170
 
171
    // Set DMA channel destination address
172
    DMA_SetDestinationAddr(channel_index,destAddress);
173
 
174
    // Set DMA channel DSCR
175
    DMA_SetDescriptorAddr(channel_index, (unsigned int)&LLI_CH[0]);
176
 
177
    // Set DMA channel control A 
178
    DMA_SetSourceBufferSize(channel_index, buffSize,
179
            (AT91C_HDMA_SRC_WIDTH_WORD >> 24),
180
            (AT91C_HDMA_DST_WIDTH_WORD >> 28), 0);
181
 
182
        //Set DMA channel control B
183
    DMA_SetSourceBufferMode(channel_index, DMA_TRANSFER_LLI,
184
                            srcAddressMode >> 24);
185
    DMA_SetDestBufferMode(channel_index, DMA_TRANSFER_LLI,
186
                            (AT91C_HDMA_DST_ADDRESS_MODE_INCR >> 28));
187
 
188
    // Set DMA channel config
189
    DMA_SetConfiguration(channel_index, BOARD_SD_DMA_HW_SRC_REQ_ID \
190
                                        | BOARD_SD_DMA_HW_DEST_REQ_ID \
191
                                        | AT91C_HDMA_SRC_REP_CONTIGUOUS_ADDR \
192
                                        | AT91C_HDMA_SRC_H2SEL_HW \
193
                                        | AT91C_HDMA_DST_REP_CONTIGUOUS_ADDR \
194
                                        | AT91C_HDMA_DST_H2SEL_SW \
195
                                        | AT91C_HDMA_SOD_DISABLE \
196
                                        | AT91C_HDMA_FIFOCFG_LARGESTBURST);
197
 
198
    // Set link list
199
    while(destAddress < ((unsigned int)(dest_addr + buffSize))) {
200
        if(((unsigned int)(dest_addr + buffSize)) - destAddress <= (4*0xFFF) )
201
        {
202
            AT91F_Prepare_Multiple_Transfer(channel_index, LLI_rownumber, LAST_ROW,
203
                                        srcAddress,
204
                                        destAddress,
205
                                        (((((unsigned int)(dest_addr + buffSize))
206
                                               - destAddress)/4)
207
                                                | AT91C_HDMA_SRC_WIDTH_WORD
208
                                                | AT91C_HDMA_DST_WIDTH_WORD),
209
                                        ( AT91C_HDMA_SIF_0
210
                                           | AT91C_HDMA_DIF_0
211
                                           | AT91C_HDMA_DST_DSCR_FETCH_FROM_MEM
212
                                           //| AT91C_HDMA_DST_DSCR_FETCH_DISABLE
213
                                           | AT91C_HDMA_DST_ADDRESS_MODE_INCR
214
                                           //| AT91C_HDMA_SRC_DSCR_FETCH_FROM_MEM
215
                                           | AT91C_HDMA_SRC_DSCR_FETCH_DISABLE
216
                                           | srcAddressMode
217
                                           | AT91C_HDMA_AUTO_DISABLE
218
                                           | AT91C_HDMA_FC_PER2MEM));
219
        }
220
        else
221
        {
222
            AT91F_Prepare_Multiple_Transfer(channel_index, LLI_rownumber, 0,
223
                                        srcAddress,
224
                                        destAddress,
225
                                        ( 0xFFF
226
                                            | AT91C_HDMA_SRC_WIDTH_WORD
227
                                            | AT91C_HDMA_DST_WIDTH_WORD),
228
                                        (AT91C_HDMA_SIF_0
229
                                            | AT91C_HDMA_DIF_0
230
                                            | AT91C_HDMA_DST_DSCR_FETCH_FROM_MEM
231
                                            //| AT91C_HDMA_DST_DSCR_FETCH_DISABLE
232
                                            | AT91C_HDMA_DST_ADDRESS_MODE_INCR
233
                                            //| AT91C_HDMA_SRC_DSCR_FETCH_FROM_MEM
234
                                            | AT91C_HDMA_SRC_DSCR_FETCH_DISABLE
235
                                            | srcAddressMode
236
                                            | AT91C_HDMA_AUTO_DISABLE
237
                                            | AT91C_HDMA_FC_PER2MEM));
238
 
239
        }
240
 
241
        destAddress += 4*0xFFF;
242
 
243
        LLI_rownumber++;
244
    }
245
 
246
    return 0;
247
}
248
 
249
 
250
static unsigned int DMACH_MCI_M2P(unsigned int channel_index,
251
                                  unsigned int* src_addr,
252
                                  unsigned int* dest_addr,
253
                                  unsigned int trans_size,
254
                                  unsigned char fifoForP)
255
{
256
    unsigned int srcAddress;
257
    unsigned int destAddress;
258
    unsigned int buffSize;
259
    unsigned int LLI_rownumber = 0;
260
    unsigned int dstAddressMode = fifoForP ?
261
                                  (AT91C_HDMA_DST_ADDRESS_MODE_INCR)
262
                                : (AT91C_HDMA_DST_ADDRESS_MODE_FIXED);
263
 
264
    // Disable dma channel
265
    DMA_DisableChannel(channel_index);
266
 
267
    buffSize = trans_size;
268
    if(buffSize >= 0x10000){
269
        buffSize = 0xffff;
270
    }
271
 
272
    // DMA channel configuration
273
    srcAddress  = (unsigned int)src_addr;    // Set the data start address
274
    destAddress = (unsigned int)dest_addr;
275
 
276
    // Set DMA channel source address
277
    DMA_SetSourceAddr(channel_index, srcAddress);
278
 
279
    // Set DMA channel destination address
280
    DMA_SetDestinationAddr(channel_index,destAddress);
281
 
282
    // Set DMA channel DSCR
283
    DMA_SetDescriptorAddr(channel_index, (unsigned int)&LLI_CH[0]);
284
 
285
    // Set DMA channel control A 
286
    DMA_SetSourceBufferSize(channel_index, buffSize,
287
                              (AT91C_HDMA_SRC_WIDTH_WORD >> 24),
288
                              (AT91C_HDMA_DST_WIDTH_WORD >> 28), 0);
289
 
290
    //Set DMA channel control B
291
    DMA_SetSourceBufferMode(channel_index,
292
                            DMA_TRANSFER_LLI,
293
                            (AT91C_HDMA_SRC_ADDRESS_MODE_INCR >> 24));
294
    DMA_SetDestBufferMode(channel_index,
295
                          DMA_TRANSFER_LLI,
296
                          dstAddressMode >> 28);
297
 
298
    // Set DMA channel config
299
    DMA_SetConfiguration(channel_index, BOARD_SD_DMA_HW_SRC_REQ_ID \
300
                                        | BOARD_SD_DMA_HW_DEST_REQ_ID \
301
                                        | AT91C_HDMA_SRC_REP_CONTIGUOUS_ADDR \
302
                                        | AT91C_HDMA_SRC_H2SEL_SW \
303
                                        | AT91C_HDMA_DST_REP_CONTIGUOUS_ADDR \
304
                                        | AT91C_HDMA_DST_H2SEL_HW \
305
                                        | AT91C_HDMA_SOD_DISABLE \
306
                                        | AT91C_HDMA_FIFOCFG_LARGESTBURST);
307
 
308
    // Set link list
309
    while(srcAddress < ((unsigned int)(src_addr + buffSize)))
310
    {
311
        if(((unsigned int)(src_addr + buffSize)) - srcAddress <= (4*0xFFF) )
312
        {
313
            AT91F_Prepare_Multiple_Transfer(channel_index, LLI_rownumber, LAST_ROW,
314
                                        srcAddress,
315
                                        destAddress,
316
                                        (((((unsigned int)(src_addr + buffSize))
317
                                                - srcAddress)/4)
318
                                                  | AT91C_HDMA_SRC_WIDTH_WORD
319
                                                  | AT91C_HDMA_DST_WIDTH_WORD),
320
                                        ( AT91C_HDMA_SIF_0
321
                                        | AT91C_HDMA_DIF_0
322
                                        //| AT91C_HDMA_DST_DSCR_FETCH_FROM_MEM
323
                                        | AT91C_HDMA_DST_DSCR_FETCH_DISABLE
324
                                        | dstAddressMode
325
                                        //| AT91C_HDMA_SRC_DSCR_FETCH_FROM_MEM
326
                                        | AT91C_HDMA_SRC_DSCR_FETCH_DISABLE
327
                                        | AT91C_HDMA_SRC_ADDRESS_MODE_INCR
328
                                        | AT91C_HDMA_AUTO_DISABLE
329
                                        | AT91C_HDMA_FC_MEM2PER));
330
        }
331
        else
332
        {
333
            AT91F_Prepare_Multiple_Transfer(channel_index, LLI_rownumber, 0,
334
                                        srcAddress,
335
                                        destAddress,
336
                                        ( 0xFFF
337
                                            | AT91C_HDMA_SRC_WIDTH_WORD
338
                                            | AT91C_HDMA_DST_WIDTH_WORD),
339
                                        ( AT91C_HDMA_SIF_0
340
                                        | AT91C_HDMA_DIF_0
341
                                        //| AT91C_HDMA_DST_DSCR_FETCH_FROM_MEM
342
                                        | AT91C_HDMA_DST_DSCR_FETCH_DISABLE
343
                                        | dstAddressMode
344
                                        | AT91C_HDMA_SRC_DSCR_FETCH_FROM_MEM
345
                                        //| AT91C_HDMA_SRC_DSCR_FETCH_DISABLE
346
                                        | AT91C_HDMA_SRC_ADDRESS_MODE_INCR
347
                                        | AT91C_HDMA_AUTO_DISABLE
348
                                        | AT91C_HDMA_FC_MEM2PER));
349
 
350
        }
351
 
352
        srcAddress += 4*0xFFF;
353
 
354
 
355
        LLI_rownumber++;
356
    }
357
 
358
    return 0;
359
}
360
 
361
static inline void DMACH_EnableIt(AT91S_MCI *pMciHw,
362
                                 unsigned int channel)
363
{
364
    unsigned int intFlag;
365
 
366
    intFlag = DMA_GetInterruptMask();
367
    intFlag |= (AT91C_HDMA_BTC0 << channel);
368
    DMA_EnableIt(intFlag);
369
}
370
#endif
371
 
372
//------------------------------------------------------------------------------
373
//         Global functions
374
//------------------------------------------------------------------------------
375
 
376
//------------------------------------------------------------------------------
377
/// Enable/disable a MCI driver instance.
378
/// \param pMci  Pointer to a MCI driver instance.
379
/// \param enb  0 for disable MCI and 1 for enable MCI.
380
//------------------------------------------------------------------------------
381
void MCI_Enable(Mci *pMci, unsigned char enb)
382
{
383
    AT91S_MCI *pMciHw = pMci->pMciHw;
384
 
385
    SANITY_CHECK(pMci);
386
    SANITY_CHECK(pMci->pMciHw);
387
 
388
    // Set the Control Register: Enable/Disable MCI interface clock
389
    if(enb == DISABLE) {
390
        MCICK_DISABLE(pMciHw);
391
    }
392
    else {
393
        MCICK_ENABLE(pMciHw);
394
    }
395
}
396
 
397
//------------------------------------------------------------------------------
398
/// Initializes a MCI driver instance and the underlying peripheral.
399
/// \param pMci    Pointer to a MCI driver instance.
400
/// \param pMciHw  Pointer to a MCI peripheral.
401
/// \param mciId   MCI peripheral identifier.
402
/// \param mode    Slot and type of supported card (max bus width).
403
//------------------------------------------------------------------------------
404
void MCI_Init(
405
    Mci *pMci,
406
    AT91S_MCI *pMciHw,
407
    unsigned char mciId,
408
    unsigned int mode)
409
{
410
    unsigned short clkDiv;
411
    unsigned int mciCfg = 0;
412
 
413
    SANITY_CHECK(pMci);
414
    SANITY_CHECK(pMciHw);
415
    SANITY_CHECK(   (mode == MCI_MMC_SLOTA)  || (mode == MCI_SD_SLOTA)
416
                 || (mode == MCI_MMC_SLOTB)  || (mode == MCI_SD_SLOTB)
417
                 || (mode == MCI_MMC4_SLOTA) || (mode == MCI_MMC4_SLOTB));
418
 
419
    // Initialize the MCI driver structure
420
    pMci->pMciHw    = pMciHw;
421
    pMci->mciId     = mciId;
422
    pMci->mciMode   = mode;
423
    pMci->semaphore = 1;
424
    pMci->pCommand  = 0;
425
 
426
    // Enable the MCI clock
427
    WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << mciId));
428
 
429
     // Reset the MCI
430
    WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_SWRST);
431
 
432
    // Disable the MCI
433
    WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS | AT91C_MCI_PWSDIS);
434
 
435
    // Disable all the interrupts
436
    WRITE_MCI(pMciHw, MCI_IDR, 0xFFFFFFFF);
437
 
438
    // Set the Data Timeout Register
439
    WRITE_MCI(pMciHw, MCI_DTOR, DTOR_1MEGA_CYCLES);
440
 
441
    // Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58)
442
    clkDiv = (BOARD_MCK / (MCI_INITIAL_SPEED * 2)) - 1;
443
    WRITE_MCI(pMciHw, MCI_MR, (clkDiv | (AT91C_MCI_PWSDIV & (0x7 << 8))));
444
 
445
    // Set the SDCard Register
446
    WRITE_MCI(pMciHw, MCI_SDCR, mode);
447
 
448
    // Enable the MCI and the Power Saving
449
    WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIEN);
450
 
451
    // Disable the DMA interface
452
    WRITE_MCI(pMciHw, MCI_DMA, AT91C_MCI_DMAEN_DISABLE);
453
 
454
    // Configure MCI
455
    //mciCfg = AT91C_MCI_FIFOMODE_AMOUNTDATA | AT91C_MCI_FERRCTRL_RWCMD;
456
    mciCfg = AT91C_MCI_FIFOMODE_ONEDATA | AT91C_MCI_FERRCTRL_RWCMD;
457
 
458
    WRITE_MCI(pMciHw, MCI_CFG, mciCfg);
459
 
460
    // Disable the MCI peripheral clock.
461
    WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << mciId));
462
}
463
 
464
//------------------------------------------------------------------------------
465
/// Close a MCI driver instance and the underlying peripheral.
466
/// \param pMci  Pointer to a MCI driver instance.
467
/// \param pMciHw  Pointer to a MCI peripheral.
468
/// \param mciId  MCI peripheral identifier.
469
//------------------------------------------------------------------------------
470
void MCI_Close(Mci *pMci)
471
{
472
    AT91S_MCI *pMciHw = pMci->pMciHw;
473
 
474
    SANITY_CHECK(pMci);
475
    SANITY_CHECK(pMciHw);
476
 
477
    // Initialize the MCI driver structure
478
    pMci->semaphore = 1;
479
    pMci->pCommand = 0;
480
 
481
    // Disable the MCI peripheral clock.
482
    WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pMci->mciId));
483
 
484
    // Disable the MCI
485
    WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS);
486
 
487
    // Disable all the interrupts
488
    WRITE_MCI(pMciHw, MCI_IDR, 0xFFFFFFFF);
489
}
490
 
491
//------------------------------------------------------------------------------
492
/// Get the  MCI CLKDIV in the MCI_MR register. The max. for MCI clock is
493
/// MCK/2 and corresponds to CLKDIV = 0
494
/// \param pMci  Pointer to the low level MCI driver.
495
/// \param mciSpeed  MCI clock speed in Hz.
496
//------------------------------------------------------------------------------
497
unsigned int MCI_GetSpeed(Mci *pMci, unsigned int *mciDiv)
498
{
499
    AT91S_MCI *pMciHw = pMci->pMciHw;
500
    unsigned int mciMr;
501
 
502
    SANITY_CHECK(pMci);
503
    SANITY_CHECK(pMci->pMciHw);
504
 
505
    // Get the Mode Register
506
    mciMr  = READ_MCI(pMciHw, MCI_MR);
507
    mciMr &= AT91C_MCI_CLKDIV;
508
    if (mciDiv) *mciDiv = mciMr;
509
    return (BOARD_MCK / 2 / (mciMr + 1));
510
}
511
 
512
//------------------------------------------------------------------------------
513
/// Configure the  MCI CLKDIV in the MCI_MR register. The max. for MCI clock is
514
/// MCK/2 and corresponds to CLKDIV = 0
515
/// \param pMci  Pointer to the low level MCI driver.
516
/// \param mciSpeed  MCI clock speed in Hz.
517
/// \param mciLimit  MCI clock limit in Hz, if not limit, set mciLimit to zero.
518
/// \return The actual speed used, 0 for fail.
519
//------------------------------------------------------------------------------
520
unsigned int MCI_SetSpeed(Mci *pMci,
521
                          unsigned int mciSpeed,
522
                          unsigned int mciLimit)
523
{
524
    AT91S_MCI *pMciHw = pMci->pMciHw;
525
    unsigned int mciMr;
526
    unsigned int clkdiv;
527
    unsigned int divLimit = 0;
528
 
529
    SANITY_CHECK(pMci);
530
    SANITY_CHECK(pMci->pMciHw);
531
 
532
    mciMr = READ_MCI(pMciHw, MCI_MR) & (~AT91C_MCI_CLKDIV);
533
 
534
    // Multimedia Card Interface clock (MCCK or MCI_CK) is Master Clock (MCK)
535
    // divided by (2*(CLKDIV+1))
536
    // mciSpeed = MCK / (2*(CLKDIV+1))
537
    if (mciLimit)   divLimit = (BOARD_MCK / 2 / mciLimit);
538
    if (mciSpeed > 0) {
539
        clkdiv = (BOARD_MCK / 2 / mciSpeed);
540
        if (mciLimit && clkdiv < divLimit)
541
            clkdiv = divLimit;
542
        if (clkdiv > 0)
543
            clkdiv -= 1;
544
        ASSERT( (clkdiv & 0xFFFFFF00) == 0, "mciSpeed too small");
545
    }
546
    else    clkdiv = 0;
547
 
548
    WRITE_MCI(pMciHw, MCI_MR, mciMr | clkdiv);
549
    return (BOARD_MCK / 2 / (clkdiv + 1));
550
}
551
 
552
//------------------------------------------------------------------------------
553
/// Configure the MCI_CFG to enable the HS mode
554
/// \param pMci     Pointer to the low level MCI driver.
555
/// \param hsEnable 1 to enable, 0 to disable HS mode.
556
//------------------------------------------------------------------------------
557
void MCI_EnableHsMode(Mci *pMci, unsigned char hsEnable)
558
{
559
    AT91S_MCI *pMciHw = pMci->pMciHw;
560
    unsigned int cfgr;
561
 
562
    SANITY_CHECK(pMci);
563
    SANITY_CHECK(pMci->pMciHw);
564
 
565
    cfgr = READ_MCI(pMciHw, MCI_CFG);
566
    if (hsEnable)   cfgr |=  AT91C_MCI_HSMODE_ENABLE;
567
    else            cfgr &= ~AT91C_MCI_HSMODE_ENABLE;
568
}
569
 
570
//------------------------------------------------------------------------------
571
/// Configure the  MCI SDCBUS in the MCI_SDCR register. Only two modes available
572
///
573
/// \param pMci  Pointer to the low level MCI driver.
574
/// \param busWidth  MCI bus width mode.
575
//------------------------------------------------------------------------------
576
void MCI_SetBusWidth(Mci *pMci, unsigned char busWidth)
577
{
578
    AT91S_MCI *pMciHw = pMci->pMciHw;
579
    unsigned int mciSdcr;
580
 
581
    SANITY_CHECK(pMci);
582
    SANITY_CHECK(pMci->pMciHw);
583
 
584
    mciSdcr = (READ_MCI(pMciHw, MCI_SDCR) & ~(AT91C_MCI_SCDBUS));
585
 
586
    WRITE_MCI(pMciHw, MCI_SDCR, mciSdcr | busWidth);
587
}
588
 
589
//------------------------------------------------------------------------------
590
/// Starts a MCI  transfer. This is a non blocking function. It will return
591
/// as soon as the transfer is started.
592
/// Return 0 if successful; otherwise returns MCI_ERROR_LOCK if the driver is
593
/// already in use.
594
/// \param pMci  Pointer to an MCI driver instance.
595
/// \param pCommand  Pointer to the command to execute.
596
//------------------------------------------------------------------------------
597
unsigned char MCI_SendCommand(Mci *pMci, MciCmd *pCommand)
598
{
599
    AT91PS_MCI pMciHw = pMci->pMciHw;
600
    unsigned int mciIer, mciMr;
601
    unsigned int transSize;
602
    unsigned int mciBlkr;
603
 
604
  #if defined(MCI_DMA_ENABLE)
605
    unsigned int mciDma;
606
  #endif
607
 
608
    SANITY_CHECK(pMci);
609
    SANITY_CHECK(pMciHw);
610
    SANITY_CHECK(pCommand);
611
 
612
    // Try to acquire the MCI semaphore
613
    if (pMci->semaphore == 0) {
614
 
615
        return MCI_ERROR_LOCK;
616
    }
617
    pMci->semaphore--;
618
 
619
    // Command is now being executed
620
    pMci->pCommand = pCommand;
621
    pCommand->status = MCI_STATUS_PENDING;
622
 
623
    // Enable the MCI peripheral clock
624
    WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << pMci->mciId));
625
 
626
    // Disable MCI clock, for multi-block data transfer
627
    MCICK_DISABLE(pMciHw);
628
 
629
    // Set Default Mode register value
630
    mciMr = READ_MCI(pMciHw, MCI_MR) & (~( AT91C_MCI_WRPROOF
631
                                          |AT91C_MCI_RDPROOF
632
                                          |AT91C_MCI_BLKLEN));
633
    // Command with DATA stage
634
    if (pCommand->blockSize && pCommand->nbBlock) {
635
        // Enable dma
636
      #if defined(MCI_DMA_ENABLE)
637
        mciDma = READ_MCI(pMciHw, MCI_DMA) | AT91C_MCI_DMAEN_ENABLE;
638
        WRITE_MCI(pMciHw, MCI_DMA, mciDma);
639
      #endif
640
 
641
        // New transfer
642
        if(pCommand->tranType == MCI_NEW_TRANSFER) {
643
 
644
            // Set block size
645
            WRITE_MCI(pMciHw, MCI_MR, mciMr | AT91C_MCI_RDPROOF
646
                                            | AT91C_MCI_WRPROOF
647
                                            |(pCommand->blockSize << 16));
648
 
649
            mciBlkr = READ_MCI(pMciHw, MCI_BLKR) & (~AT91C_MCI_BCNT);
650
            WRITE_MCI(pMciHw, MCI_BLKR, mciBlkr | pCommand->nbBlock);
651
        }
652
 
653
        transSize = (pCommand->nbBlock * pCommand->blockSize) / 4;
654
        if ((pCommand->blockSize & 0x3) != 0)
655
            transSize++;
656
 
657
        // DATA transfer from card to host
658
        if (pCommand->isRead) {
659
 
660
          #if defined(MCI_DMA_ENABLE)
661
            DMACH_MCI_P2M(BOARD_MCI_DMA_CHANNEL,
662
                          (unsigned int*)&pMciHw->MCI_FIFO,
663
                          (unsigned int*) pCommand->pData,
664
                          transSize, 1);
665
            DMACH_EnableIt(pMciHw, BOARD_MCI_DMA_CHANNEL);
666
            DMA_EnableChannel(BOARD_MCI_DMA_CHANNEL);
667
            mciIer = AT91C_MCI_DMADONE | STATUS_ERRORS;
668
          #else 
669
            mciIer = AT91C_MCI_CMDRDY | STATUS_ERRORS;
670
          #endif
671
        }
672
        // DATA transfer from host to card
673
        else {
674
 
675
          #if defined(MCI_DMA_ENABLE)
676
            DMACH_MCI_M2P(BOARD_MCI_DMA_CHANNEL,
677
                          (unsigned int*) pCommand->pData,
678
                          (unsigned int*)&pMciHw->MCI_FIFO,
679
                          transSize, 1);
680
            DMACH_EnableIt(pMciHw, BOARD_MCI_DMA_CHANNEL);
681
            DMA_EnableChannel(BOARD_MCI_DMA_CHANNEL);
682
            mciIer = AT91C_MCI_DMADONE | STATUS_ERRORS;
683
          #else
684
            mciIer = AT91C_MCI_CMDRDY | STATUS_ERRORS;
685
          #endif
686
        }
687
    }
688
    // Start an infinite block transfer (but no data in current command)
689
    else if (pCommand->dataTran) {
690
        // Set block size
691
        WRITE_MCI(pMciHw, MCI_MR, mciMr | AT91C_MCI_RDPROOF
692
                                        | AT91C_MCI_WRPROOF
693
                                        |(pCommand->blockSize << 16));
694
        // Set data length: 0
695
        mciBlkr = READ_MCI(pMciHw, MCI_BLKR) & (~AT91C_MCI_BCNT);
696
        WRITE_MCI(pMciHw, MCI_BLKR, mciBlkr);
697
        mciIer = AT91C_MCI_CMDRDY | STATUS_ERRORS;
698
    }
699
    // No data transfer: stop at the end of the command
700
    else{
701
        WRITE_MCI(pMciHw, MCI_MR, mciMr);
702
        mciIer = AT91C_MCI_CMDRDY | STATUS_ERRORS;
703
    }
704
 
705
    // Enable MCI clock
706
    MCICK_ENABLE(pMciHw);
707
 
708
    // Send the command
709
    if((pCommand->tranType != MCI_CONTINUE_TRANSFER)
710
        || (pCommand->blockSize == 0)) {
711
 
712
        WRITE_MCI(pMciHw, MCI_ARGR, pCommand->arg);
713
        WRITE_MCI(pMciHw, MCI_CMDR, pCommand->cmd);
714
    }
715
 
716
    // Ignore data error
717
    mciIer &= ~(  AT91C_MCI_UNRE
718
                | AT91C_MCI_OVRE
719
                | AT91C_MCI_DTOE
720
                | AT91C_MCI_DCRCE
721
                | AT91C_MCI_BLKOVRE
722
                | AT91C_MCI_CSTOE);
723
 
724
    // Interrupt enable shall be done after PDC TXTEN and RXTEN
725
    WRITE_MCI(pMciHw, MCI_IER, mciIer);
726
 
727
    return 0;
728
}
729
 
730
//------------------------------------------------------------------------------
731
/// Check NOTBUSY and DTIP bits of status register on the given MCI driver.
732
/// Return value, 0 for bus ready, 1 for bus busy
733
/// \param pMci  Pointer to a MCI driver instance.
734
//------------------------------------------------------------------------------
735
unsigned char MCI_CheckBusy(Mci *pMci)
736
{
737
    AT91S_MCI *pMciHw = pMci->pMciHw;
738
    volatile unsigned int status;
739
 
740
    // Enable MCI clock
741
    MCICK_ENABLE(pMciHw);
742
 
743
    status = READ_MCI(pMciHw, MCI_SR);
744
 
745
    if(    ((status & AT91C_MCI_NOTBUSY)!=0)
746
        && ((status & AT91C_MCI_DTIP)==0)
747
        ) {
748
 
749
        // Disable MCI clock
750
        MCICK_DISABLE(pMciHw);
751
 
752
        return 0;
753
    }
754
    else {
755
        return 1;
756
    }
757
}
758
 
759
//------------------------------------------------------------------------------
760
/// Check BLKE bit of status register on the given MCI driver.
761
/// \param pMci  Pointer to a MCI driver instance.
762
//------------------------------------------------------------------------------
763
unsigned char MCI_CheckBlke(Mci *pMci)
764
{
765
    AT91S_MCI *pMciHw = pMci->pMciHw;
766
    unsigned int status;
767
 
768
    status = READ_MCI(pMciHw, MCI_SR);
769
    // TRACE_DEBUG("status %x\n\r",status);
770
 
771
    if((status & AT91C_MCI_BLKE)!=0) {
772
        return 0;
773
    }
774
    else {
775
        return 1;
776
    }
777
}
778
 
779
//------------------------------------------------------------------------------
780
/// Processes pending events on the given MCI driver.
781
/// \param pMci  Pointer to a MCI driver instance.
782
//------------------------------------------------------------------------------
783
void MCI_Handler(Mci *pMci)
784
{
785
    AT91S_MCI *pMciHw = pMci->pMciHw;
786
    volatile MciCmd *pCommand = pMci->pCommand;
787
    volatile unsigned int status, status0, mask;
788
    unsigned char i;
789
 
790
    SANITY_CHECK(pMci);
791
    SANITY_CHECK(pMciHw);
792
    SANITY_CHECK(pCommand);
793
 
794
    // Read the status register
795
    status0 = READ_MCI(pMciHw, MCI_SR);
796
    mask    = READ_MCI(pMciHw, MCI_IMR);
797
    //TRACE_INFO("iST %x\n\r", status);
798
    status  = status0 & mask;
799
    //TRACE_INFO("iSM %x\n\r", status);
800
 
801
    // Check if an error has occured
802
    if ((status & STATUS_ERRORS) != 0) {
803
 
804
        // Check error code
805
        if ((status & STATUS_ERRORS) == AT91C_MCI_RTOE) {
806
 
807
            pCommand->status = MCI_STATUS_NORESPONSE;
808
        }
809
        // if the command is SEND_OP_COND the CRC error flag is always present
810
        // (cf : R3 response)
811
        else if ((   (status & STATUS_ERRORS) != AT91C_MCI_RCRCE)
812
                  || (   (pCommand->cmd != SDCARD_APP_OP_COND_CMD)
813
                      && (pCommand->cmd != MMC_SEND_OP_COND_CMD))) {
814
 
815
            pCommand->status = MCI_STATUS_ERROR;
816
        }
817
        // printf("iErr%x\n\r", (status & STATUS_ERRORS));
818
    }
819
    mask &= ~STATUS_ERRORS;
820
 
821
    // Check if a command has been completed
822
    if (status & AT91C_MCI_CMDRDY) {
823
 
824
        WRITE_MCI(pMciHw, MCI_IDR, AT91C_MCI_CMDRDY);
825
        if (pCommand->isRead == 0 &&
826
            pCommand->tranType == MCI_STOP_TRANSFER) {
827
            if (status0 & AT91C_MCI_XFRDONE) {
828
                MCICK_DISABLE(pMciHw);
829
            }
830
            else {
831
                WRITE_MCI(pMciHw, MCI_IER, AT91C_MCI_XFRDONE);
832
            }
833
        }
834
        else {
835
            mask &= ~AT91C_MCI_CMDRDY;
836
            if (pCommand->dataTran == 0) {
837
                MCICK_DISABLE(pMciHw);
838
            }
839
        }
840
    }
841
 
842
    // Check if transfer stopped
843
    if (status & AT91C_MCI_XFRDONE) {
844
        mask &= ~AT91C_MCI_XFRDONE;
845
        MCICK_DISABLE(pMciHw);
846
    }
847
 
848
#if defined(MCI_DMA_ENABLE)
849
 
850
    // Check FIFOEMPTY
851
    if (status & AT91C_MCI_FIFOEMPTY) {
852
        mask &= ~AT91C_MCI_FIFOEMPTY;
853
        MCICK_DISABLE(pMciHw);
854
    }
855
 
856
    // Check if a DMA transfer has been completed
857
    if (status & AT91C_MCI_DMADONE) {
858
 
859
        unsigned int intFlag;
860
        intFlag = DMA_GetInterruptMask();
861
        intFlag = ~intFlag;
862
        intFlag |= (AT91C_HDMA_BTC0 << BOARD_MCI_DMA_CHANNEL);
863
        DMA_DisableIt(intFlag);
864
 
865
        WRITE_MCI(pMciHw, MCI_IDR, AT91C_MCI_DMADONE);
866
        if ( pCommand->isRead == 0 &&
867
            (status0 & AT91C_MCI_FIFOEMPTY) == 0 ) {
868
            WRITE_MCI(pMciHw, MCI_IER, AT91C_MCI_FIFOEMPTY);
869
        }
870
        else {
871
            MCICK_DISABLE(pMciHw);
872
            mask &= ~AT91C_MCI_DMADONE;
873
        }
874
    }
875
#endif
876
 
877
    // All non-error mask done, complete the command
878
    if (!mask || pCommand->status != MCI_STATUS_PENDING) {
879
 
880
        // Store the card response in the provided buffer
881
        if (pCommand->pResp) {
882
            unsigned char resSize;
883
            switch (pCommand->resType) {
884
            case 1: case 3: case 4: case 5: case 6: case 7:
885
                     resSize = 1;           break;
886
            case 2:  resSize = 4;           break;
887
            default: resSize = 0;           break;
888
            }
889
            for (i=0; i < resSize; i++) {
890
                pCommand->pResp[i] = READ_MCI(pMciHw, MCI_RSPR[0]);
891
            }
892
        }
893
 
894
        // If no error occured, the transfer is successful
895
        if (pCommand->status == MCI_STATUS_PENDING)
896
            pCommand->status = 0;
897
 
898
        // Disable interrupts
899
        WRITE_MCI(pMciHw, MCI_IDR, READ_MCI(pMciHw, MCI_IMR));
900
 
901
        // Release the semaphore
902
        pMci->semaphore++;
903
 
904
        // Invoke the callback associated with the current command (if any)
905
        if (pCommand->callback) {
906
            (pCommand->callback)(pCommand->status, (void*)pCommand);
907
        }
908
    }
909
}
910
 
911
//------------------------------------------------------------------------------
912
/// Returns 1 if the given MCI transfer is complete; otherwise returns 0.
913
/// \param pCommand  Pointer to a MciCmd instance.
914
//------------------------------------------------------------------------------
915
unsigned char MCI_IsTxComplete(MciCmd *pCommand)
916
{
917
    if (pCommand->status != MCI_STATUS_PENDING) {
918
        if (pCommand->status != 0) {
919
            TRACE_DEBUG("MCI_IsTxComplete %d\n\r", pCommand->status);
920
        }
921
        return 1;
922
    }
923
    else {
924
        return 0;
925
    }
926
}
927
 
928
//------------------------------------------------------------------------------
929
/// Check whether the MCI is using the FIFO transfer mode
930
/// \param pMci  Pointer to a Mci instance.
931
/// \param pCommand  Pointer to a MciCmd instance.
932
//------------------------------------------------------------------------------
933
unsigned int MCI_FifoTransfer(Mci *pMci, MciCmd *pCommand)
934
{
935
    unsigned int status=0;
936
    unsigned int nbTransfer=0;
937
    unsigned int i;
938
    AT91S_MCI *pMciHw = pMci->pMciHw;
939
    unsigned int *pMem;
940
 
941
    SANITY_CHECK(pMci);
942
    SANITY_CHECK(pCommand);
943
 
944
    // If using DMA mode, return
945
#if defined(MCI_DMA_ENABLE)
946
    return 0;
947
#endif
948
 
949
    TRACE_DEBUG("MCIFifo:%d,%d\n\r", pCommand->isRead, pCommand->nbBlock);
950
 
951
    if (pCommand->nbBlock == 0 || pCommand->blockSize == 0)
952
        return 0;
953
 
954
    pMem = (unsigned int*)pCommand->pData;
955
 
956
    // Get transfer size
957
    nbTransfer = (pCommand->blockSize) * (pCommand->nbBlock) / 4;
958
    if((pCommand->blockSize) * (pCommand->nbBlock) % 4) {
959
        nbTransfer++;
960
    }
961
 
962
    if (pCommand->isRead) {
963
 
964
        // Read RDR loop
965
        for(i=0; i<nbTransfer; i++) {
966
            while(1) {
967
                status = READ_MCI(pMciHw, MCI_SR);
968
                if (status & AT91C_MCI_RXRDY)
969
                    break;
970
              #if 1
971
                if (status & STATUS_ERRORS_DATA) {
972
                    TRACE_ERROR("MCI_FifoTransfer.R: 0x%x\n\r", status);
973
                    return status;
974
                }
975
              #endif
976
            }
977
            *pMem = READ_MCI(pMciHw, MCI_RDR);
978
            pMem++;
979
        }
980
    }
981
    else {
982
 
983
        // Write TDR loop
984
        for(i=0; i<nbTransfer; i++) {
985
            while(1) {
986
                status = READ_MCI(pMciHw, MCI_SR);
987
                if (status & (AT91C_MCI_TXRDY | AT91C_MCI_NOTBUSY))
988
                    break;
989
              #if 0
990
                if (status & STATUS_ERRORS_DATA) {
991
                    TRACE_ERROR("MCI_FifoTransfer.W: 0x%x\n\r", status);
992
                    return status;
993
                }
994
              #endif
995
            }
996
            WRITE_MCI(pMciHw, MCI_TDR, *pMem);
997
            pMem++;
998
        }
999
    }
1000
 
1001
    status = READ_MCI(pMciHw, MCI_SR);
1002
    TRACE_DEBUG("MCI_FifoTransfer : All status %x\n\r", status);
1003
    status &= READ_MCI(pMciHw, MCI_IMR);
1004
    TRACE_DEBUG("MCI_FifoTransfer : Masked status %x\n\r", status);
1005
 
1006
  #if 0
1007
  { unsigned int old = status;
1008
    while(status & AT91C_MCI_DTIP) {
1009
        status = READ_MCI(pMciHw, MCI_SR);
1010
        if (status != old) {
1011
            old = status;
1012
            TRACE_DEBUG_WP(" -> %x", status);
1013
        }
1014
    }
1015
    TRACE_DEBUG_WP("\n\r");
1016
    TRACE_DEBUG(" DPIT 0 stat %x\n\r", status);
1017
    while((status & (AT91C_MCI_FIFOEMPTY
1018
                        | AT91C_MCI_BLKE
1019
                        | AT91C_MCI_XFRDONE)) == 0) {
1020
        status = READ_MCI(pMciHw, MCI_SR);
1021
    }
1022
    TRACE_DEBUG(" FIFO EMPTY stat %x\n\r", status);
1023
  }
1024
  #endif
1025
 
1026
    return status;
1027
}

powered by: WebSVN 2.1.0

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