1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_specification.h"
10 #include "fsl_card.h"
11 
12 /*******************************************************************************
13  * Variables
14  ******************************************************************************/
15 SDK_ALIGN(uint32_t g_sdmmc[SDK_SIZEALIGN(SDMMC_GLOBAL_BUFFER_SIZE, SDMMC_DATA_BUFFER_ALIGN_CAHCE)],
16           MAX(SDMMC_DATA_BUFFER_ALIGN_CAHCE, HOST_DMA_BUFFER_ADDR_ALIGN));
17 /*******************************************************************************
18  * Code
19  ******************************************************************************/
20 
SDMMC_Delay(uint32_t num)21 void SDMMC_Delay(uint32_t num)
22 {
23     volatile uint32_t i, j;
24 
25     for (i = 0U; i < num; i++)
26     {
27         for (j = 0U; j < 10000U; j++)
28         {
29             __asm("nop");
30         }
31     }
32 }
33 
SDMMC_SelectCard(HOST_TYPE * base,HOST_TRANSFER_FUNCTION transfer,uint32_t relativeAddress,bool isSelected)34 status_t SDMMC_SelectCard(HOST_TYPE *base, HOST_TRANSFER_FUNCTION transfer, uint32_t relativeAddress, bool isSelected)
35 {
36     assert(transfer);
37 
38     HOST_TRANSFER content = {0};
39     HOST_COMMAND command = {0};
40 
41     command.index = kSDMMC_SelectCard;
42     if (isSelected)
43     {
44         command.argument = relativeAddress << 16U;
45         command.responseType = kCARD_ResponseTypeR1;
46     }
47     else
48     {
49         command.argument = 0U;
50         command.responseType = kCARD_ResponseTypeNone;
51     }
52 
53     content.command = &command;
54     content.data = NULL;
55     if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & kSDMMC_R1ErrorAllFlag))
56     {
57         return kStatus_SDMMC_TransferFailed;
58     }
59 
60     /* Wait until card to transfer state */
61     return kStatus_Success;
62 }
63 
SDMMC_SendApplicationCommand(HOST_TYPE * base,HOST_TRANSFER_FUNCTION transfer,uint32_t relativeAddress)64 status_t SDMMC_SendApplicationCommand(HOST_TYPE *base, HOST_TRANSFER_FUNCTION transfer, uint32_t relativeAddress)
65 {
66     assert(transfer);
67 
68     HOST_TRANSFER content = {0};
69     HOST_COMMAND command = {0};
70 
71     command.index = kSDMMC_ApplicationCommand;
72     command.argument = (relativeAddress << 16U);
73     command.responseType = kCARD_ResponseTypeR1;
74 
75     content.command = &command;
76     content.data = 0U;
77     if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & kSDMMC_R1ErrorAllFlag))
78     {
79         return kStatus_SDMMC_TransferFailed;
80     }
81 
82     if (!(command.response[0U] & kSDMMC_R1ApplicationCommandFlag))
83     {
84         return kStatus_SDMMC_CardNotSupport;
85     }
86 
87     return kStatus_Success;
88 }
89 
SDMMC_SetBlockCount(HOST_TYPE * base,HOST_TRANSFER_FUNCTION transfer,uint32_t blockCount)90 status_t SDMMC_SetBlockCount(HOST_TYPE *base, HOST_TRANSFER_FUNCTION transfer, uint32_t blockCount)
91 {
92     assert(transfer);
93 
94     HOST_TRANSFER content = {0};
95     HOST_COMMAND command = {0};
96 
97     command.index = kSDMMC_SetBlockCount;
98     command.argument = blockCount;
99     command.responseType = kCARD_ResponseTypeR1;
100 
101     content.command = &command;
102     content.data = 0U;
103     if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & kSDMMC_R1ErrorAllFlag))
104     {
105         return kStatus_SDMMC_TransferFailed;
106     }
107 
108     return kStatus_Success;
109 }
110 
SDMMC_GoIdle(HOST_TYPE * base,HOST_TRANSFER_FUNCTION transfer)111 status_t SDMMC_GoIdle(HOST_TYPE *base, HOST_TRANSFER_FUNCTION transfer)
112 {
113     assert(transfer);
114 
115     HOST_TRANSFER content = {0};
116     HOST_COMMAND command = {0};
117 
118     command.index = kSDMMC_GoIdleState;
119 
120     content.command = &command;
121     content.data = 0U;
122     if (kStatus_Success != transfer(base, &content))
123     {
124         return kStatus_SDMMC_TransferFailed;
125     }
126 
127     return kStatus_Success;
128 }
129 
SDMMC_SetBlockSize(HOST_TYPE * base,HOST_TRANSFER_FUNCTION transfer,uint32_t blockSize)130 status_t SDMMC_SetBlockSize(HOST_TYPE *base, HOST_TRANSFER_FUNCTION transfer, uint32_t blockSize)
131 {
132     assert(transfer);
133 
134     HOST_TRANSFER content = {0};
135     HOST_COMMAND command = {0};
136 
137     command.index = kSDMMC_SetBlockLength;
138     command.argument = blockSize;
139     command.responseType = kCARD_ResponseTypeR1;
140 
141     content.command = &command;
142     content.data = 0U;
143     if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & kSDMMC_R1ErrorAllFlag))
144     {
145         return kStatus_SDMMC_TransferFailed;
146     }
147 
148     return kStatus_Success;
149 }
150 
SDMMC_SetCardInactive(HOST_TYPE * base,HOST_TRANSFER_FUNCTION transfer)151 status_t SDMMC_SetCardInactive(HOST_TYPE *base, HOST_TRANSFER_FUNCTION transfer)
152 {
153     assert(transfer);
154 
155     HOST_TRANSFER content = {0};
156     HOST_COMMAND command = {0};
157 
158     command.index = kSDMMC_GoInactiveState;
159     command.argument = 0U;
160     command.responseType = kCARD_ResponseTypeNone;
161 
162     content.command = &command;
163     content.data = 0U;
164     if ((kStatus_Success != transfer(base, &content)))
165     {
166         return kStatus_SDMMC_TransferFailed;
167     }
168 
169     return kStatus_Success;
170 }
171 
SDMMC_SwitchVoltage(HOST_TYPE * base,HOST_TRANSFER_FUNCTION transfer)172 status_t SDMMC_SwitchVoltage(HOST_TYPE *base, HOST_TRANSFER_FUNCTION transfer)
173 {
174     assert(transfer);
175 
176     HOST_TRANSFER content = {0};
177     HOST_COMMAND command = {0};
178 
179     command.index = kSD_VoltageSwitch;
180     command.argument = 0U;
181     command.responseType = kCARD_ResponseTypeR1;
182 
183     content.command = &command;
184     content.data = NULL;
185     if (kStatus_Success != transfer(base, &content))
186     {
187         return kStatus_SDMMC_TransferFailed;
188     }
189     /* disable card clock */
190     HOST_ENABLE_CARD_CLOCK(base, false);
191 
192     /* check data line and cmd line status */
193     if ((GET_HOST_STATUS(base) &
194          (CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY)) != 0U)
195     {
196         return kStatus_SDMMC_SwitchVoltageFail;
197     }
198 
199     /* host switch to 1.8V */
200     HOST_SWITCH_VOLTAGE180V(base, true);
201 
202     SDMMC_Delay(100U);
203 
204     /*enable sd clock*/
205     HOST_ENABLE_CARD_CLOCK(base, true);
206     /*enable force clock on*/
207     HOST_FORCE_SDCLOCK_ON(base, true);
208     /* dealy 1ms,not exactly correct when use while */
209     SDMMC_Delay(10U);
210     /*disable force clock on*/
211     HOST_FORCE_SDCLOCK_ON(base, false);
212 
213     /* check data line and cmd line status */
214     if ((GET_HOST_STATUS(base) &
215          (CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY)) == 0U)
216     {
217         return kStatus_SDMMC_SwitchVoltageFail;
218     }
219 
220     return kStatus_Success;
221 }
222 
SDMMC_ExecuteTuning(HOST_TYPE * base,HOST_TRANSFER_FUNCTION transfer,uint32_t tuningCmd,uint32_t blockSize)223 status_t SDMMC_ExecuteTuning(HOST_TYPE *base, HOST_TRANSFER_FUNCTION transfer, uint32_t tuningCmd, uint32_t blockSize)
224 {
225     HOST_TRANSFER content = {0U};
226     HOST_COMMAND command = {0U};
227     HOST_DATA data = {0U};
228     uint32_t buffer[32U] = {0U};
229     bool tuningError = true;
230 
231     command.index = tuningCmd;
232     command.argument = 0U;
233     command.responseType = kCARD_ResponseTypeR1;
234 
235     data.blockSize = blockSize;
236     data.blockCount = 1U;
237     data.rxData = buffer;
238     /* add this macro for adpter to different driver */
239     HOST_ENABLE_TUNING_FLAG(data);
240 
241     content.command = &command;
242     content.data = &data;
243 
244     /* enable the standard tuning */
245     HOST_EXECUTE_STANDARD_TUNING_ENABLE(base, true);
246 
247     while (true)
248     {
249         /* send tuning block */
250         if ((kStatus_Success != transfer(base, &content)))
251         {
252             return kStatus_SDMMC_TransferFailed;
253         }
254         SDMMC_Delay(1U);
255 
256         /*wait excute tuning bit clear*/
257         if ((HOST_EXECUTE_STANDARD_TUNING_STATUS(base) != 0U))
258         {
259             continue;
260         }
261 
262         /* if tuning error , re-tuning again */
263         if ((HOST_CHECK_TUNING_ERROR(base) != 0U) && tuningError)
264         {
265             tuningError = false;
266             /* enable the standard tuning */
267             HOST_EXECUTE_STANDARD_TUNING_ENABLE(base, true);
268             HOST_ADJUST_TUNING_DELAY(base, HOST_STANDARD_TUNING_START);
269         }
270         else
271         {
272             break;
273         }
274     }
275 
276     /* delay to wait the host controller stable */
277     SDMMC_Delay(100U);
278 
279     /* check tuning result*/
280     if (HOST_EXECUTE_STANDARD_TUNING_RESULT(base) == 0U)
281     {
282         return kStatus_SDMMC_TuningFail;
283     }
284 
285     HOST_AUTO_STANDARD_RETUNING_TIMER(base);
286 
287     return kStatus_Success;
288 }
289