LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
Main Page
Related Pages
Modules
Data Structures
Files
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_Type
*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_Type
*pSDMMC)
83
{}
84
85
/* Set block size for transfer */
86
void
IP_SDMMC_SetBlkSize
(
IP_SDMMC_001_Type
*pSDMMC,
uint32_t
bytes)
87
{
88
pSDMMC->
BLKSIZ
= bytes;
89
}
90
91
/* Reset card in slot */
92
void
IP_SDMMC_Reset
(
IP_SDMMC_001_Type
*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
/* Enable or disable slot power */
103
void
IP_SDMMC_PowerOnOff
(
IP_SDMMC_001_Type
*pSDMMC, int32_t enable)
104
{
105
if
(enable) {
106
pSDMMC->
PWREN
= 1;
107
}
108
else
{
109
pSDMMC->
PWREN
= 0;
110
}
111
}
112
113
/* Detect if write protect is enabled */
114
int32_t
IP_SDMMC_CardWpOn
(
IP_SDMMC_001_Type
*pSDMMC)
115
{
116
if
(pSDMMC->
WRTPRT
& 1) {
117
return
1;
118
}
119
return
0;
120
}
121
122
/* Detect if an SD card is inserted */
123
int32_t
IP_SDMMC_CardNDetect
(
IP_SDMMC_001_Type
*pSDMMC)
124
{
125
/* No card = high state in regsiter */
126
if
(pSDMMC->
CDETECT
& 1) {
127
return
0;
128
}
129
130
return
1;
131
}
132
133
/* Function to send command to Card interface unit (CIU) */
134
int32_t
IP_SDMMC_SendCmd
(
IP_SDMMC_001_Type
*pSDMMC,
uint32_t
cmd
,
uint32_t
arg)
135
{
136
volatile
int32_t tmo = 50;
137
volatile
int
delay
;
138
139
/* set command arg reg*/
140
pSDMMC->
CMDARG
= arg;
141
pSDMMC->
CMD
=
MCI_CMD_START
|
cmd
;
142
143
/* poll untill command is accepted by the CIU */
144
while
(--tmo && (pSDMMC->
CMD
&
MCI_CMD_START
)) {
145
if
(tmo & 1) {
146
delay = 50;
147
}
148
else
{
149
delay = 18000;
150
}
151
152
while
(--delay > 1) {}
153
}
154
155
return
(tmo < 1) ? 1 : 0;
156
}
157
158
/* Read the response from the last command */
159
void
IP_SDMMC_GetResponse
(
IP_SDMMC_001_Type
*pSDMMC,
uint32_t
*resp)
160
{
161
/* on this chip response is not a fifo so read all 4 regs */
162
resp[0] = pSDMMC->
RESP0
;
163
resp[1] = pSDMMC->
RESP1
;
164
resp[2] = pSDMMC->
RESP2
;
165
resp[3] = pSDMMC->
RESP3
;
166
}
167
168
/* Sets the SD bus clock speed */
169
void
IP_SDMMC_SetClock
(
IP_SDMMC_001_Type
*pSDMMC,
uint32_t
clk_rate,
uint32_t
speed)
170
{
171
/* compute SD/MMC clock dividers */
172
uint32_t
div;
173
174
div = ((clk_rate / speed) + 2) >> 1;
175
176
if
((div == pSDMMC->
CLKDIV
) && pSDMMC->
CLKENA
) {
177
return
;
/* Closest speed is already set */
178
179
}
180
/* disable clock */
181
pSDMMC->
CLKENA
= 0;
182
183
/* User divider 0 */
184
pSDMMC->
CLKSRC
=
MCI_CLKSRC_CLKDIV0
;
185
186
/* inform CIU */
187
IP_SDMMC_SendCmd
(pSDMMC,
MCI_CMD_UPD_CLK
|
MCI_CMD_PRV_DAT_WAIT
, 0);
188
189
/* set divider 0 to desired value */
190
pSDMMC->
CLKDIV
=
MCI_CLOCK_DIVIDER
(0, div);
191
192
/* inform CIU */
193
IP_SDMMC_SendCmd
(pSDMMC,
MCI_CMD_UPD_CLK
|
MCI_CMD_PRV_DAT_WAIT
, 0);
194
195
/* enable clock */
196
pSDMMC->
CLKENA
=
MCI_CLKEN_ENABLE
;
197
198
/* inform CIU */
199
IP_SDMMC_SendCmd
(pSDMMC,
MCI_CMD_UPD_CLK
|
MCI_CMD_PRV_DAT_WAIT
, 0);
200
}
201
202
/* Function to set card type */
203
void
IP_SDMMC_SetCardType
(
IP_SDMMC_001_Type
*pSDMMC,
uint32_t
ctype)
204
{
205
pSDMMC->
CTYPE
= ctype;
206
}
207
208
/* Function to clear interrupt & FIFOs */
209
void
IP_SDMMC_SetClearIntFifo
(
IP_SDMMC_001_Type
*pSDMMC)
210
{
211
/* reset all blocks */
212
pSDMMC->
CTRL
|=
MCI_CTRL_FIFO_RESET
;
213
214
/* wait till resets clear */
215
while
(pSDMMC->
CTRL
&
MCI_CTRL_FIFO_RESET
) {}
216
217
/* Clear interrupt status */
218
pSDMMC->
RINTSTS
= 0xFFFFFFFF;
219
}
220
221
/* Returns the raw SD interface interrupt status */
222
uint32_t
IP_SDMMC_GetRawIntStatus
(
IP_SDMMC_001_Type
*pSDMMC)
223
{
224
return
pSDMMC->
RINTSTS
;
225
}
226
227
/* Sets the raw SD interface interrupt status */
228
void
IP_SDMMC_SetRawIntStatus
(
IP_SDMMC_001_Type
*pSDMMC,
uint32_t
iVal)
229
{
230
pSDMMC->
RINTSTS
= iVal;
231
}
232
233
/* Sets the SD interface interrupt mask */
234
void
IP_SDMMC_SetIntMask
(
IP_SDMMC_001_Type
*pSDMMC,
uint32_t
iVal)
235
{
236
pSDMMC->
INTMASK
= iVal;
237
}
238
239
/* Setup DMA descriptors */
240
void
IP_SDMMC_DmaSetup
(
IP_SDMMC_001_Type
*pSDMMC,
sdif_device
*psdif_dev,
uint32_t
addr,
uint32_t
size)
241
{
242
int
i = 0;
243
uint32_t
ctrl, maxs;
244
245
/* Reset DMA */
246
pSDMMC->
CTRL
|=
MCI_CTRL_DMA_RESET
|
MCI_CTRL_FIFO_RESET
;
247
while
(pSDMMC->
CTRL
&
MCI_CTRL_DMA_RESET
) {}
248
249
/* Build a descriptor list using the chained DMA method */
250
while
(size > 0) {
251
/* Limit size of the transfer to maximum buffer size */
252
maxs = size;
253
if
(maxs >
MCI_DMADES1_MAXTR
) {
254
maxs =
MCI_DMADES1_MAXTR
;
255
}
256
size -= maxs;
257
258
/* Set buffer size */
259
psdif_dev->
mci_dma_dd
[i].
des1
=
MCI_DMADES1_BS1
(maxs);
260
261
/* Setup buffer address (chained) */
262
psdif_dev->
mci_dma_dd
[i].
des2
= addr + (i *
MCI_DMADES1_MAXTR
);
263
264
/* Setup basic control */
265
ctrl =
MCI_DMADES0_OWN
|
MCI_DMADES0_CH
;
266
if
(i == 0) {
267
ctrl |=
MCI_DMADES0_FS
;
/* First DMA buffer */
268
269
}
270
/* No more data? Then this is the last descriptor */
271
if
(!size) {
272
ctrl |=
MCI_DMADES0_LD
;
273
}
274
else
{
275
ctrl |=
MCI_DMADES0_DIC
;
276
}
277
278
/* Another descriptor is needed */
279
psdif_dev->
mci_dma_dd
[i].
des3
= (
uint32_t
) &psdif_dev->
mci_dma_dd
[i + 1];
280
psdif_dev->
mci_dma_dd
[i].
des0
= ctrl;
281
282
i++;
283
}
284
285
/* Set DMA derscriptor base address */
286
pSDMMC->
DBADDR
= (
uint32_t
) &psdif_dev->
mci_dma_dd
[0];
287
}
288
295
void
IP_SDMMC_SetBlockSize
(
IP_SDMMC_001_Type
*pSDMMC,
uint32_t
blk_size)
296
{
297
/* set block size and byte count */
298
pSDMMC->
BLKSIZ
= blk_size;
299
pSDMMC->
BYTCNT
= blk_size;
300
}
software
lpc_core
lpc_ip
sdmmc_001.c
Generated on Fri Nov 16 2012 13:36:43 for LPCOpen Platform by
1.8.2