1 /*******************************************************************************
2 * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * PolarFire SoC MSS eMMC SD Interface Level Driver.
7 *
8 * This eMMC/SD Interface driver provides functions for transferring
9 * configuration and programming commands to the eMMC/SD device. Functions
10 * contained within the eMMC/SD interface driver are accessed through the
11 * mss_mmc_if.h header file.
12 *
13 */
14 #include "mss_mmc_if.h"
15 #include "mss_mmc_regs.h"
16 #include "mss_mmc_types.h"
17
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21
22 #define MMC_CLEAR 0u
23 #define MMC_SET 1u
24 #define SHIFT_16BIT 16u
25 #define DELAY_COUNT 0xFFFFu
26
27 /***************************************************************************//**
28 * Local Function Prototypes
29 */
30 static cif_response_t response_1_parser(void);
31 static uint32_t process_request_checkresptype(uint8_t responsetype);
32 static cif_response_t cq_execute_task(uint8_t task_id);
33 /***************************************************************************//**
34 * cif_send_cmd()
35 * See ".h" for details of how to use this function.
36 */
cif_send_cmd(uint32_t cmd_arg,uint32_t cmd_type,uint8_t resp_type)37 cif_response_t cif_send_cmd
38 (
39 uint32_t cmd_arg,
40 uint32_t cmd_type,
41 uint8_t resp_type
42 )
43 {
44 uint32_t trans_status_isr;
45 cif_response_t ret_status = TRANSFER_IF_FAIL;
46
47 /* clear all status interrupts except:
48 * current limit error, card interrupt, card removal, card insertion */
49 MMC->SRS12 = ~(SRS12_CURRENT_LIMIT_ERROR
50 | SRS12_CARD_INTERRUPT
51 | SRS12_CARD_REMOVAL
52 | SRS12_CARD_INSERTION);
53
54 /* Transfer the Command to the MMC device */
55 send_mmc_cmd(cmd_arg, cmd_type, resp_type, CHECK_IF_CMD_SENT_POLL);
56
57 /* No responses for CMD 0,4,15 */
58 if ((MMC_CMD_0_GO_IDLE_STATE != cmd_type) && (MMC_CMD_4_SET_DSR != cmd_type)
59 && (MMC_CMD_15_GOTO_INACTIVE_STATE != cmd_type))
60 {
61 trans_status_isr = MMC->SRS12;
62
63 if (SRS12_COMMAND_COMPLETE == (trans_status_isr & SRS12_COMMAND_COMPLETE))
64 {
65 /* If the response is an R1/B response */
66 if ((MSS_MMC_RESPONSE_R1 == resp_type) || (MSS_MMC_RESPONSE_R1B == resp_type))
67 {
68 ret_status = response_1_parser();
69 }
70 else
71 {
72 ret_status = TRANSFER_IF_SUCCESS;
73 }
74 }
75 else if (SRS12_ERROR_INTERRUPT == (SRS12_ERROR_INTERRUPT & trans_status_isr))
76 {
77 ret_status = TRANSFER_IF_FAIL;
78 }
79 else
80 {
81 ret_status = TRANSFER_IF_FAIL;
82 }
83 }
84 else
85 {
86 ret_status = TRANSFER_IF_SUCCESS;
87 }
88 /* clear flags for the next time */
89 MMC->SRS12 = ~(SRS12_CURRENT_LIMIT_ERROR
90 | SRS12_CARD_INTERRUPT
91 | SRS12_CARD_REMOVAL
92 | SRS12_CARD_INSERTION);
93
94 return(ret_status);
95 }
96
97 /***************************************************************************//**
98 * The send_mmc_cmd() function transfers the eMMC/SD command and argument to the
99 * eMMC/SD device and waits until the core indicates that the command has been
100 * transferred successfully.
101 */
send_mmc_cmd(uint32_t cmd_arg,uint32_t cmd_type,uint8_t resp_type,cmd_response_check_options cmd_option)102 void send_mmc_cmd
103 (
104 uint32_t cmd_arg,
105 uint32_t cmd_type,
106 uint8_t resp_type,
107 cmd_response_check_options cmd_option
108 )
109 {
110 uint32_t command_information;
111 uint32_t srs9, trans_status_isr;
112
113 /* check if command line is not busy */
114 do
115 {
116 srs9 = MMC->SRS09;
117 }while ((srs9 & SRS9_CMD_INHIBIT_CMD) != NO_CMD_INHIBIT);
118
119 command_information = process_request_checkresptype(resp_type);
120
121 MMC->SRS02 = cmd_arg;
122 MMC->SRS03 = (uint32_t)((cmd_type << CMD_SHIFT) | command_information);
123
124 switch (cmd_option)
125 {
126 /* only need to wait around if expecting no response */
127 case CHECK_IF_CMD_SENT_POLL:
128 do
129 {
130 trans_status_isr = MMC->SRS12;
131 }while (((SRS12_COMMAND_COMPLETE | SRS12_ERROR_INTERRUPT) & trans_status_isr) == MMC_CLEAR);
132 break;
133 case CHECK_IF_CMD_SENT_INT:
134 break;
135 case CHECK_IF_CMD_SENT_NO: /* use when expecting a response */
136 /* No check- will be checked when response received */
137 break;
138 default:
139 /* nothing */
140 break;
141 }
142 }
143
144 /***************************************************************************//**
145 * The response_1_parser() returns the contents of the Card Status Register.
146 * This function checks that none of the error fields are set within the CSR
147 * and the status of the READY_FOR_DATA flag (Bit 8).
148 */
response_1_parser(void)149 static cif_response_t response_1_parser(void)
150 {
151 cif_response_t ret_status = TRANSFER_IF_FAIL;
152 uint32_t response;
153
154 response = MMC->SRS04;
155 if (MMC_CLEAR == (CARD_STATUS_ALL_ERRORS_MASK & response)) /* no error */
156 {
157 if ((CARD_STATUS_READY_FOR_DATA & response) != MMC_CLEAR)
158 {
159 ret_status = TRANSFER_IF_SUCCESS;
160 }
161 else
162 {
163 ret_status = DEVICE_BUSY;
164 }
165 }
166 return(ret_status);
167 }
168
169 /*****************************************************************************/
process_request_checkresptype(uint8_t responsetype)170 static uint32_t process_request_checkresptype(uint8_t responsetype)
171 {
172 uint32_t command_information;
173
174 /* check response type */
175 switch (responsetype) {
176 default:
177 case MSS_MMC_RESPONSE_NO_RESP:
178 command_information = (uint32_t)SRS3_NO_RESPONSE;
179 break;
180 case MSS_MMC_RESPONSE_R2:
181 command_information = (uint32_t)(SRS3_RESP_LENGTH_136
182 | SRS3_CRC_CHECK_EN);
183 break;
184 case MSS_MMC_RESPONSE_R3:
185 case MSS_MMC_RESPONSE_R4:
186 command_information = (uint32_t)SRS3_RESP_LENGTH_48;
187 break;
188 case MSS_MMC_RESPONSE_R1:
189 case MSS_MMC_RESPONSE_R5:
190 case MSS_MMC_RESPONSE_R6:
191 case MSS_MMC_RESPONSE_R7:
192 command_information = (uint32_t)(SRS3_RESP_LENGTH_48
193 | SRS3_CRC_CHECK_EN
194 | SRS3_INDEX_CHECK_EN);
195 break;
196 case MSS_MMC_RESPONSE_R1B:
197 case MSS_MMC_RESPONSE_R5B:
198 command_information = (uint32_t)(SRS3_RESP_LENGTH_48B
199 | SRS3_CRC_CHECK_EN
200 | SRS3_INDEX_CHECK_EN);
201
202 break;
203 }
204
205 return (command_information);
206 }
207
208 /******************************************************************************/
cif_send_cq_direct_command(uint8_t * desc_base_addr,uint32_t cmd_arg,uint32_t cmd_type,uint8_t resp_type,uint8_t task_id)209 cif_response_t cif_send_cq_direct_command
210 (
211 uint8_t *desc_base_addr,
212 uint32_t cmd_arg,
213 uint32_t cmd_type,
214 uint8_t resp_type,
215 uint8_t task_id
216 )
217 {
218
219 uint32_t *dcmdTaskDesc;
220 uint32_t flags;
221 uint32_t desc_offset;
222 uint32_t reg;
223 uint32_t cmd_response;
224 cif_response_t ret_status = TRANSFER_IF_FAIL;
225
226 /* Enable direct command */
227 reg = MMC->CQRS02;
228 reg |= (uint32_t)CQRS02_DIRECT_CMD_ENABLE;
229 MMC->CQRS02 = reg;
230
231 desc_offset = CQ_HOST_NUMBER_OF_TASKS * task_id;
232
233 dcmdTaskDesc = (uint32_t *)(desc_base_addr + desc_offset);
234
235 /* first prepare general task flags */
236 flags = (uint32_t)(CQ_DESC_VALID | CQ_DESC_END | CQ_DESC_ACT_TASK | CQ_DESC_INT);
237
238 /* now prepare direct command specific flags */
239 flags |= ((cmd_type & 0x3FU) << SHIFT_16BIT);
240
241 switch (resp_type)
242 {
243 case MSS_MMC_RESPONSE_NO_RESP:
244 flags |= (uint32_t)CQ_DESC_DCMD_RESP_TYPE_NO_RESP;
245 break;
246 case MSS_MMC_RESPONSE_R1:
247 case MSS_MMC_RESPONSE_R4:
248 case MSS_MMC_RESPONSE_R5:
249 flags |= (uint32_t)CQ_DESC_DCMD_RESP_TYPE_R1_R4_R5;
250 break;
251 case MSS_MMC_RESPONSE_R1B:
252 flags |= (uint32_t)CQ_DESC_DCMD_RESP_TYPE_R1B;
253 break;
254 default:
255 /* nothing */
256 break;
257 }
258
259 flags |= (uint32_t)CQ_DESC_DCMD_CMD_TIMING;
260
261 dcmdTaskDesc[0] = flags;
262 dcmdTaskDesc[1] = cmd_arg << SHIFT_16BIT;
263 dcmdTaskDesc[2] = MMC_CLEAR;
264 dcmdTaskDesc[3] = MMC_CLEAR;
265
266 dcmdTaskDesc[4] = (uint32_t)(CQ_DESC_VALID | CQ_DESC_END | CQ_DESC_ACT_NOP);
267 dcmdTaskDesc[5] = MMC_CLEAR;
268 dcmdTaskDesc[6] = MMC_CLEAR;
269 dcmdTaskDesc[7] = MMC_CLEAR;
270
271 ret_status = cq_execute_task(task_id);
272
273 cmd_response = MMC->CQRS18;
274
275 reg = MMC->CQRS02;
276 reg &= ~(uint32_t)CQRS02_DIRECT_CMD_ENABLE;
277 MMC->CQRS02 = reg;
278
279 if (TRANSFER_IF_SUCCESS == ret_status)
280 {
281 if ((CARD_STATUS_ALL_ERRORS_MASK & cmd_response) == MMC_CLEAR) /* no error */
282 {
283 if ((CARD_STATUS_READY_FOR_DATA & cmd_response) != MMC_CLEAR)
284 {
285 ret_status = TRANSFER_IF_SUCCESS;
286 }
287 else
288 {
289 ret_status = DEVICE_BUSY;
290 }
291 }
292 }
293 return ret_status;
294 }
295
296 /******************************************************************************/
cq_execute_task(uint8_t task_id)297 static cif_response_t cq_execute_task(uint8_t task_id)
298 {
299
300 cif_response_t ret_status = TRANSFER_IF_FAIL;
301 uint32_t reg;
302 uint32_t trans_status_isr;
303 uint32_t cmd_response;
304 uint32_t value = DELAY_COUNT;
305
306 /* Set doorbell to start processing descriptors by controller */
307 reg = MMC_SET << task_id;
308 MMC->CQRS10 = reg;
309
310 while (value--);
311
312 do
313 {
314 trans_status_isr = MMC->SRS12;
315 }while (((SRS12_ERROR_INTERRUPT | SRS12_CMD_QUEUING_INT) & trans_status_isr) == MMC_CLEAR);
316
317 if ((trans_status_isr & (SRS12_ERROR_INTERRUPT | SRS12_CMD_QUEUING_INT)) != MMC_CLEAR)
318 {
319 trans_status_isr = MMC->SRS12;
320 MMC->SRS12 = trans_status_isr;
321
322 if ((trans_status_isr & SRS12_ERROR_INTERRUPT) != MMC_CLEAR)
323 {
324 ret_status = TRANSFER_IF_FAIL;
325 }
326 if ((trans_status_isr & SRS12_CMD_QUEUING_INT) != MMC_CLEAR)
327 {
328 reg = MMC->CQRS04;
329 MMC->CQRS04 = reg;
330
331 if ((reg & CQRS04_RESP_ERR_INT) != MMC_CLEAR)
332 {
333 ret_status = TRANSFER_IF_FAIL;
334 }
335
336 if ((reg & CQRS04_TASK_COMPLETE_INT) != MMC_CLEAR)
337 {
338 reg = MMC->CQRS11;
339 /* clear all caught notifications */
340 MMC->CQRS11 = reg;
341 if (task_id == CQ_DCMD_TASK_ID)
342 {
343 if ((reg & (MMC_SET << task_id)) != MMC_CLEAR)
344 {
345 cmd_response = MMC->CQRS18;
346 ret_status = TRANSFER_IF_SUCCESS;
347 }
348 }
349 else
350 {
351 ret_status = TRANSFER_IF_SUCCESS;
352 }
353 }
354 }
355 }
356 else
357 {
358 ret_status = TRANSFER_IF_FAIL;
359 }
360 return ret_status;
361 }
362 /******************************************************************************/
363 #ifdef __cplusplus
364 }
365 #endif
366