LPCOpen Platform for LPC18XX/43XX microcontrollers  18XX43XX
LPCOpen Platform for the NXP LPC18XX/43XX family of Microcontrollers
sdif_18xx_43xx.c
Go to the documentation of this file.
1 /*
2  * @brief LPC18xx/43xx SD/SDIO driver
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 "chip.h"
33 #include "string.h"
34 
35 /*****************************************************************************
36  * Private types/enumerations/variables
37  ****************************************************************************/
38 
39 /*****************************************************************************
40  * Public types/enumerations/variables
41  ****************************************************************************/
42 
43 /*****************************************************************************
44  * Private functions
45  ****************************************************************************/
46 
47 /*****************************************************************************
48  * Public functions
49  ****************************************************************************/
50 
51 /* Initializes the SD/MMC controller */
53 {
54  /* Enable SDIO module clock */
55  Chip_Clock_EnableOpts(CLK_MX_SDIO, true, true, 1);
56 
57  /* Software reset */
58  pSDMMC->BMOD = MCI_BMOD_SWR;
59 
60  /* reset all blocks */
63 
64  /* Internal DMA setup for control register */
66  pSDMMC->INTMASK = 0;
67 
68  /* Clear the interrupts for the host controller */
69  pSDMMC->RINTSTS = 0xFFFFFFFF;
70 
71  /* Put in max timeout */
72  pSDMMC->TMOUT = 0xFFFFFFFF;
73 
74  /* FIFO threshold settings for DMA, DMA burst of 4, FIFO watermark at 16 */
76 
77  /* Enable internal DMA, burst size of 4, fixed burst */
78  pSDMMC->BMOD = MCI_BMOD_DE | MCI_BMOD_PBL4 | MCI_BMOD_DSL(4);
79 
80  /* disable clock to CIU (needs latch) */
81  pSDMMC->CLKENA = 0;
82  pSDMMC->CLKSRC = 0;
83 }
84 
85 /* Shutdown the SD/MMC controller */
87 {
88  /* Disable the clock */
90 }
91 
92 /* Function to send command to Card interface unit (CIU) */
93 int32_t Chip_SDIF_SendCmd(LPC_SDMMC_T *pSDMMC, uint32_t cmd, uint32_t arg)
94 {
95  volatile int32_t tmo = 50;
96  volatile int delay;
97 
98  /* set command arg reg*/
99  pSDMMC->CMDARG = arg;
100  pSDMMC->CMD = MCI_CMD_START | cmd;
101 
102  /* poll untill command is accepted by the CIU */
103  while (--tmo && (pSDMMC->CMD & MCI_CMD_START)) {
104  if (tmo & 1) {
105  delay = 50;
106  }
107  else {
108  delay = 18000;
109  }
110 
111  while (--delay > 1) {}
112  }
113 
114  return (tmo < 1) ? 1 : 0;
115 }
116 
117 /* Read the response from the last command */
118 void Chip_SDIF_GetResponse(LPC_SDMMC_T *pSDMMC, uint32_t *resp)
119 {
120  /* on this chip response is not a fifo so read all 4 regs */
121  resp[0] = pSDMMC->RESP0;
122  resp[1] = pSDMMC->RESP1;
123  resp[2] = pSDMMC->RESP2;
124  resp[3] = pSDMMC->RESP3;
125 }
126 
127 /* Sets the SD bus clock speed */
128 void Chip_SDIF_SetClock(LPC_SDMMC_T *pSDMMC, uint32_t clk_rate, uint32_t speed)
129 {
130  /* compute SD/MMC clock dividers */
131  uint32_t div;
132 
133  div = ((clk_rate / speed) + 2) >> 1;
134 
135  if ((div == pSDMMC->CLKDIV) && pSDMMC->CLKENA) {
136  return; /* Closest speed is already set */
137 
138  }
139  /* disable clock */
140  pSDMMC->CLKENA = 0;
141 
142  /* User divider 0 */
143  pSDMMC->CLKSRC = MCI_CLKSRC_CLKDIV0;
144 
145  /* inform CIU */
147 
148  /* set divider 0 to desired value */
149  pSDMMC->CLKDIV = MCI_CLOCK_DIVIDER(0, div);
150 
151  /* inform CIU */
153 
154  /* enable clock */
155  pSDMMC->CLKENA = MCI_CLKEN_ENABLE;
156 
157  /* inform CIU */
159 }
160 
161 /* Function to clear interrupt & FIFOs */
163 {
164  /* reset all blocks */
165  pSDMMC->CTRL |= MCI_CTRL_FIFO_RESET;
166 
167  /* wait till resets clear */
168  while (pSDMMC->CTRL & MCI_CTRL_FIFO_RESET) {}
169 
170  /* Clear interrupt status */
171  pSDMMC->RINTSTS = 0xFFFFFFFF;
172 }
173 
174 /* Setup DMA descriptors */
175 void Chip_SDIF_DmaSetup(LPC_SDMMC_T *pSDMMC, sdif_device *psdif_dev, uint32_t addr, uint32_t size)
176 {
177  int i = 0;
178  uint32_t ctrl, maxs;
179 
180  /* Reset DMA */
182  while (pSDMMC->CTRL & MCI_CTRL_DMA_RESET) {}
183 
184  /* Build a descriptor list using the chained DMA method */
185  while (size > 0) {
186  /* Limit size of the transfer to maximum buffer size */
187  maxs = size;
188  if (maxs > MCI_DMADES1_MAXTR) {
189  maxs = MCI_DMADES1_MAXTR;
190  }
191  size -= maxs;
192 
193  /* Set buffer size */
194  psdif_dev->mci_dma_dd[i].des1 = MCI_DMADES1_BS1(maxs);
195 
196  /* Setup buffer address (chained) */
197  psdif_dev->mci_dma_dd[i].des2 = addr + (i * MCI_DMADES1_MAXTR);
198 
199  /* Setup basic control */
201  if (i == 0) {
202  ctrl |= MCI_DMADES0_FS; /* First DMA buffer */
203 
204  }
205  /* No more data? Then this is the last descriptor */
206  if (!size) {
207  ctrl |= MCI_DMADES0_LD;
208  }
209  else {
210  ctrl |= MCI_DMADES0_DIC;
211  }
212 
213  /* Another descriptor is needed */
214  psdif_dev->mci_dma_dd[i].des3 = (uint32_t) &psdif_dev->mci_dma_dd[i + 1];
215  psdif_dev->mci_dma_dd[i].des0 = ctrl;
216 
217  i++;
218  }
219 
220  /* Set DMA derscriptor base address */
221  pSDMMC->DBADDR = (uint32_t) &psdif_dev->mci_dma_dd[0];
222 }
223