LPCOpen Platform for LPC18XX/43XX microcontrollers: C:/w/lpcopen_docs/software/lpc_core/lpc_chip/chip_18xx_43xx/sdif_18xx_43xx.c Source File

| LPCOpen Platform for LPC18XX/43XX microcontrollers 18XX43XX LPCOpen Platform for the NXP LPC18XX/43XX family of Microcontrollers

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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 */
52 void Chip_SDIF_Init(LPC_SDMMC_T *pSDMMC)
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 */
61 pSDMMC->CTRL = MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET | MCI_CTRL_DMA_RESET;
62 while (pSDMMC->CTRL & (MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET | MCI_CTRL_DMA_RESET)) {}
63
64 /* Internal DMA setup for control register */
65 pSDMMC->CTRL = MCI_CTRL_USE_INT_DMAC | MCI_CTRL_INT_ENABLE;
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 */
75 pSDMMC->FIFOTH = MCI_FIFOTH_DMA_MTS_4 | MCI_FIFOTH_RX_WM((SD_FIFO_SZ / 2) - 1) | MCI_FIFOTH_TX_WM(SD_FIFO_SZ / 2);
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 */
86 void Chip_SDIF_DeInit(LPC_SDMMC_T *pSDMMC)
87 {
88 /* Disable the clock */
89 Chip_Clock_Disable(CLK_MX_SDIO);
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 */
146 Chip_SDIF_SendCmd(pSDMMC, MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0);
147
148 /* set divider 0 to desired value */
149 pSDMMC->CLKDIV = MCI_CLOCK_DIVIDER(0, div);
150
151 /* inform CIU */
152 Chip_SDIF_SendCmd(pSDMMC, MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0);
153
154 /* enable clock */
155 pSDMMC->CLKENA = MCI_CLKEN_ENABLE;
156
157 /* inform CIU */
158 Chip_SDIF_SendCmd(pSDMMC, MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0);
159 }
160
161 /* Function to clear interrupt & FIFOs */
162 void Chip_SDIF_SetClearIntFifo(LPC_SDMMC_T *pSDMMC)
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 */
181 pSDMMC->CTRL |= MCI_CTRL_DMA_RESET | MCI_CTRL_FIFO_RESET;
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 */
200 ctrl = MCI_DMADES0_OWN | MCI_DMADES0_CH;
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