LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 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 */
52 {
53  /* Software reset */
54  pSDMMC->BMOD = MCI_BMOD_SWR;
55 
56  /* reset all blocks */
59 
60  /* Internal DMA setup for control register */
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 */
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 */
83 {}
84 
85 /* Set block size for transfer */
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 */
115 {
116  if (pSDMMC->WRTPRT & 1) {
117  return 1;
118  }
119  return 0;
120 }
121 
122 /* Detect if an SD card is inserted */
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) */
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 */
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 */
188 
189  /* set divider 0 to desired value */
190  pSDMMC->CLKDIV = MCI_CLOCK_DIVIDER(0, div);
191 
192  /* inform CIU */
194 
195  /* enable clock */
196  pSDMMC->CLKENA = MCI_CLKEN_ENABLE;
197 
198  /* inform CIU */
200 }
201 
202 /* Function to set card type */
204 {
205  pSDMMC->CTYPE = ctype;
206 }
207 
208 /* Function to clear interrupt & FIFOs */
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 */
223 {
224  return pSDMMC->RINTSTS;
225 }
226 
227 /* Sets the raw SD interface interrupt status */
229 {
230  pSDMMC->RINTSTS = iVal;
231 }
232 
233 /* Sets the SD interface interrupt mask */
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 */
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 */
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 
296 {
297  /* set block size and byte count */
298  pSDMMC->BLKSIZ = blk_size;
299  pSDMMC->BYTCNT = blk_size;
300 }