LPCOpen Platform  v1.03
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_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) */
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 */
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 */
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 */
157 
158  /* set divider 0 to desired value */
159  pSDMMC->CLKDIV = MCI_CLOCK_DIVIDER(0, div);
160 
161  /* inform CIU */
163 
164  /* enable clock */
165  pSDMMC->CLKENA = MCI_CLKEN_ENABLE;
166 
167  /* inform CIU */
169 }
170 
171 /* Function to set card type */
173 {
174  pSDMMC->CTYPE = ctype;
175 }
176 
177 /* Function to clear interrupt & FIFOs */
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 */
192 {
193  return pSDMMC->RINTSTS;
194 }
195 
196 /* Sets the raw SD interface interrupt status */
198 {
199  pSDMMC->RINTSTS = iVal;
200 }
201 
202 /* Sets the SD interface interrupt mask */
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 */
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 */
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 */
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 */
268 {
269  /* set byte count */
270  pSDMMC->BYTCNT = bytes;
271 }
272