| 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