LPCOpen Platform
v1.03
LPCOpen Platform for NXP LPC Microcontrollers
Main Page
Modules
Data Structures
Files
Related Pages
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
sdmmc_001.c
Go to the documentation of this file.
1
/*
2
* @brief SD/SDIO (MCI) registers and control functions
3
*
4
* @note
5
* Copyright(C) NXP Semiconductors, 2012
6
* All rights reserved.
7
*
8
* @par
9
* Software that is described herein is for illustrative purposes only
10
* which provides customers with programming information regarding the
11
* LPC products. This software is supplied "AS IS" without any warranties of
12
* any kind, and NXP Semiconductors and its licensor disclaim any and
13
* all warranties, express or implied, including all implied warranties of
14
* merchantability, fitness for a particular purpose and non-infringement of
15
* intellectual property rights. NXP Semiconductors assumes no responsibility
16
* or liability for the use of the software, conveys no license or rights under any
17
* patent, copyright, mask work right, or any other intellectual property rights in
18
* or to any products. NXP Semiconductors reserves the right to make changes
19
* in the software without notification. NXP Semiconductors also makes no
20
* representation or warranty that such application will be suitable for the
21
* specified use without further testing or modification.
22
*
23
* @par
24
* Permission to use, copy, modify, and distribute this software and its
25
* documentation is hereby granted, under NXP Semiconductors' and its
26
* licensor's relevant copyrights in the software, without fee, provided that it
27
* is used in conjunction with NXP Semiconductors microcontrollers. This
28
* copyright, permission, and disclaimer notice must appear in all copies of
29
* this code.
30
*/
31
32
#include "
sdmmc_001.h
"
33
34
/*****************************************************************************
35
* Private types/enumerations/variables
36
****************************************************************************/
37
38
/*****************************************************************************
39
* Public types/enumerations/variables
40
****************************************************************************/
41
42
/*****************************************************************************
43
* Private functions
44
****************************************************************************/
45
46
/*****************************************************************************
47
* Public functions
48
****************************************************************************/
49
50
/* Initializes the MCI card controller */
51
void
IP_SDMMC_Init
(
IP_SDMMC_001_T
*pSDMMC)
52
{
53
/* Software reset */
54
pSDMMC->
BMOD
=
MCI_BMOD_SWR
;
55
56
/* reset all blocks */
57
pSDMMC->
CTRL
=
MCI_CTRL_RESET
|
MCI_CTRL_FIFO_RESET
|
MCI_CTRL_DMA_RESET
;
58
while
(pSDMMC->
CTRL
& (
MCI_CTRL_RESET
|
MCI_CTRL_FIFO_RESET
|
MCI_CTRL_DMA_RESET
)) {}
59
60
/* Internal DMA setup for control register */
61
pSDMMC->
CTRL
=
MCI_CTRL_USE_INT_DMAC
|
MCI_CTRL_INT_ENABLE
;
62
pSDMMC->
INTMASK
= 0;
63
64
/* Clear the interrupts for the host controller */
65
pSDMMC->
RINTSTS
= 0xFFFFFFFF;
66
67
/* Put in max timeout */
68
pSDMMC->
TMOUT
= 0xFFFFFFFF;
69
70
/* FIFO threshold settings for DMA, DMA burst of 4, FIFO watermark at 16 */
71
pSDMMC->
FIFOTH
=
MCI_FIFOTH_DMA_MTS_4
|
MCI_FIFOTH_RX_WM
((
SD_FIFO_SZ
/ 2) - 1) |
MCI_FIFOTH_TX_WM
(
SD_FIFO_SZ
/ 2);
72
73
/* Enable internal DMA, burst size of 4, fixed burst */
74
pSDMMC->
BMOD
=
MCI_BMOD_DE
|
MCI_BMOD_PBL4
|
MCI_BMOD_DSL
(4);
75
76
/* disable clock to CIU (needs latch) */
77
pSDMMC->
CLKENA
= 0;
78
pSDMMC->
CLKSRC
= 0;
79
}
80
81
/* Close the MCI */
82
void
IP_SDMMC_DeInit
(
IP_SDMMC_001_T
*pSDMMC)
83
{}
84
85
/* Set block size for transfer */
86
void
IP_SDMMC_SetBlkSize
(
IP_SDMMC_001_T
*pSDMMC,
uint32_t
bytes
)
87
{
88
pSDMMC->
BLKSIZ
=
bytes
;
89
}
90
91
/* Reset card in slot */
92
void
IP_SDMMC_Reset
(
IP_SDMMC_001_T
*pSDMMC, int32_t reset)
93
{
94
if
(reset) {
95
pSDMMC->
RST_N
= 1;
96
}
97
else
{
98
pSDMMC->
RST_N
= 0;
99
}
100
}
101
102
/* Function to send command to Card interface unit (CIU) */
103
int32_t
IP_SDMMC_SendCmd
(
IP_SDMMC_001_T
*pSDMMC,
uint32_t
cmd,
uint32_t
arg)
104
{
105
volatile
int32_t tmo = 50;
106
volatile
int
delay
;
107
108
/* set command arg reg*/
109
pSDMMC->
CMDARG
= arg;
110
pSDMMC->
CMD
=
MCI_CMD_START
| cmd;
111
112
/* poll untill command is accepted by the CIU */
113
while
(--tmo && (pSDMMC->
CMD
&
MCI_CMD_START
)) {
114
if
(tmo & 1) {
115
delay = 50;
116
}
117
else
{
118
delay = 18000;
119
}
120
121
while
(--delay > 1) {}
122
}
123
124
return
(tmo < 1) ? 1 : 0;
125
}
126
127
/* Read the response from the last command */
128
void
IP_SDMMC_GetResponse
(
IP_SDMMC_001_T
*pSDMMC,
uint32_t
*resp)
129
{
130
/* on this chip response is not a fifo so read all 4 regs */
131
resp[0] = pSDMMC->
RESP0
;
132
resp[1] = pSDMMC->
RESP1
;
133
resp[2] = pSDMMC->
RESP2
;
134
resp[3] = pSDMMC->
RESP3
;
135
}
136
137
/* Sets the SD bus clock speed */
138
void
IP_SDMMC_SetClock
(
IP_SDMMC_001_T
*pSDMMC,
uint32_t
clk_rate,
uint32_t
speed
)
139
{
140
/* compute SD/MMC clock dividers */
141
uint32_t
div;
142
143
div = ((clk_rate /
speed
) + 2) >> 1;
144
145
if
((div == pSDMMC->
CLKDIV
) && pSDMMC->
CLKENA
) {
146
return
;
/* Closest speed is already set */
147
148
}
149
/* disable clock */
150
pSDMMC->
CLKENA
= 0;
151
152
/* User divider 0 */
153
pSDMMC->
CLKSRC
=
MCI_CLKSRC_CLKDIV0
;
154
155
/* inform CIU */
156
IP_SDMMC_SendCmd
(pSDMMC,
MCI_CMD_UPD_CLK
|
MCI_CMD_PRV_DAT_WAIT
, 0);
157
158
/* set divider 0 to desired value */
159
pSDMMC->
CLKDIV
=
MCI_CLOCK_DIVIDER
(0, div);
160
161
/* inform CIU */
162
IP_SDMMC_SendCmd
(pSDMMC,
MCI_CMD_UPD_CLK
|
MCI_CMD_PRV_DAT_WAIT
, 0);
163
164
/* enable clock */
165
pSDMMC->
CLKENA
=
MCI_CLKEN_ENABLE
;
166
167
/* inform CIU */
168
IP_SDMMC_SendCmd
(pSDMMC,
MCI_CMD_UPD_CLK
|
MCI_CMD_PRV_DAT_WAIT
, 0);
169
}
170
171
/* Function to set card type */
172
void
IP_SDMMC_SetCardType
(
IP_SDMMC_001_T
*pSDMMC,
uint32_t
ctype)
173
{
174
pSDMMC->
CTYPE
= ctype;
175
}
176
177
/* Function to clear interrupt & FIFOs */
178
void
IP_SDMMC_SetClearIntFifo
(
IP_SDMMC_001_T
*pSDMMC)
179
{
180
/* reset all blocks */
181
pSDMMC->
CTRL
|=
MCI_CTRL_FIFO_RESET
;
182
183
/* wait till resets clear */
184
while
(pSDMMC->
CTRL
&
MCI_CTRL_FIFO_RESET
) {}
185
186
/* Clear interrupt status */
187
pSDMMC->
RINTSTS
= 0xFFFFFFFF;
188
}
189
190
/* Returns the raw SD interface interrupt status */
191
uint32_t
IP_SDMMC_GetRawIntStatus
(
IP_SDMMC_001_T
*pSDMMC)
192
{
193
return
pSDMMC->
RINTSTS
;
194
}
195
196
/* Sets the raw SD interface interrupt status */
197
void
IP_SDMMC_SetRawIntStatus
(
IP_SDMMC_001_T
*pSDMMC,
uint32_t
iVal)
198
{
199
pSDMMC->
RINTSTS
= iVal;
200
}
201
202
/* Sets the SD interface interrupt mask */
203
void
IP_SDMMC_SetIntMask
(
IP_SDMMC_001_T
*pSDMMC,
uint32_t
iVal)
204
{
205
pSDMMC->
INTMASK
= iVal;
206
}
207
208
/* Setup DMA descriptors */
209
void
IP_SDMMC_DmaSetup
(
IP_SDMMC_001_T
*pSDMMC,
sdif_device
*psdif_dev,
uint32_t
addr,
uint32_t
size)
210
{
211
int
i = 0;
212
uint32_t
ctrl, maxs;
213
214
/* Reset DMA */
215
pSDMMC->
CTRL
|=
MCI_CTRL_DMA_RESET
|
MCI_CTRL_FIFO_RESET
;
216
while
(pSDMMC->
CTRL
&
MCI_CTRL_DMA_RESET
) {}
217
218
/* Build a descriptor list using the chained DMA method */
219
while
(size > 0) {
220
/* Limit size of the transfer to maximum buffer size */
221
maxs = size;
222
if
(maxs >
MCI_DMADES1_MAXTR
) {
223
maxs =
MCI_DMADES1_MAXTR
;
224
}
225
size -= maxs;
226
227
/* Set buffer size */
228
psdif_dev->
mci_dma_dd
[i].
des1
=
MCI_DMADES1_BS1
(maxs);
229
230
/* Setup buffer address (chained) */
231
psdif_dev->
mci_dma_dd
[i].
des2
= addr + (i *
MCI_DMADES1_MAXTR
);
232
233
/* Setup basic control */
234
ctrl =
MCI_DMADES0_OWN
|
MCI_DMADES0_CH
;
235
if
(i == 0) {
236
ctrl |=
MCI_DMADES0_FS
;
/* First DMA buffer */
237
238
}
239
/* No more data? Then this is the last descriptor */
240
if
(!size) {
241
ctrl |=
MCI_DMADES0_LD
;
242
}
243
else
{
244
ctrl |=
MCI_DMADES0_DIC
;
245
}
246
247
/* Another descriptor is needed */
248
psdif_dev->
mci_dma_dd
[i].
des3
= (
uint32_t
) &psdif_dev->
mci_dma_dd
[i + 1];
249
psdif_dev->
mci_dma_dd
[i].
des0
= ctrl;
250
251
i++;
252
}
253
254
/* Set DMA derscriptor base address */
255
pSDMMC->
DBADDR
= (
uint32_t
) &psdif_dev->
mci_dma_dd
[0];
256
}
257
258
/* Sets the transfer block size and byte count */
259
void
IP_SDMMC_SetBlkSizeByteCnt
(
IP_SDMMC_001_T
*pSDMMC,
uint32_t
blk_size)
260
{
261
/* set block size and byte count */
262
pSDMMC->
BLKSIZ
= blk_size;
263
pSDMMC->
BYTCNT
= blk_size;
264
}
265
266
/* Sets the transfer byte count */
267
void
IP_SDMMC_SetByteCnt
(
IP_SDMMC_001_T
*pSDMMC,
uint32_t
bytes
)
268
{
269
/* set byte count */
270
pSDMMC->
BYTCNT
=
bytes
;
271
}
272
software
lpc_core
lpc_ip
sdmmc_001.c
Generated on Fri May 10 2013 10:42:19 for LPCOpen Platform by
1.8.2