1 // ==========================================================================
6 // MMC card driver for MXC platform
8 // ==========================================================================
9 //####ECOSGPLCOPYRIGHTBEGIN####
10 // -------------------------------------------
11 // This file is part of eCos, the Embedded Configurable Operating System.
12 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
44 // Author(s): Lewis Liu <weizhi.liu@freescale.com>
45 // Contributors: Lewis Liu <weizhi.liu@freescale.com>
46 // Date: 2008-05-13 Initial version
50 //####DESCRIPTIONEND####
52 //==========================================================================
54 #include <cyg/io/mxcmci_host.h>
55 #include <cyg/io/mxcmci_core.h>
56 #include <cyg/io/mxcmci_mmc.h>
58 static cyg_uint32 sd_get_rca(void);
59 static cyg_uint32 sd_get_bit_mode_support(void);
60 static cyg_uint32 sd_set_bus_width(cyg_uint32);
61 static cyg_uint32 sd_set_high_speed_mode(void);
63 #define SD_OCR_VALUE_HV_LC 0x00ff8000 /* nirp_oct07: <- 3.3v, LC */
64 #define SD_OCR_VALUE_HV_HC 0x40ff8000 /* nirp_oct07: <- 3.3v, HC */
65 /* nirp_oct07: LV_LC not needed - 1.8v is only supported under eSD which supports HC by default (SD>2.00) */
66 #define SD_OCR_VALUE_LV_HC 0x40000080 /* nirp_oct07: <- 1.8v, HC */
68 #define SD_OCR_HC_RES 0x40000000
69 #define SD_OCR_LC_RES 0x00000000
71 #define SD_IF_HV_COND_ARG 0x000001AA
72 #define SD_IF_LV_COND_ARG 0x000002AA
75 #define SD_R1_STATUS_APP_CMD_MSK 0x20
76 #define BIT_MODE_4_SUPPORT 5
77 #define SD_BUS_WIDTH_OFFSET 6
79 #define SD_STATUS_LEN 64
81 #define SD_BOOT_SWITCH_ARG 0x80FFFF2F
82 #define SD_PARTITION1 0x01000000
84 cyg_uint32 sd_init(cyg_uint32 bus_width)
86 cyg_uint32 status = FAIL;
87 cyg_uint32 bus_size = bus_width;
89 /* Get CID number of SD Memory Card */
90 if (!mxcmci_get_cid()) {
91 //diag_printf("%s:mxcmci_get_cid OK!\n", __FUNCTION__);
92 /* Set RCA of the SD Card */
94 //diag_printf("%s:sd_get_rca OK!\n", __FUNCTION__);
95 /*Get CSD from Card */
99 /*Enable operating frequency */
100 host_cfg_clock(OPERATING_FREQ);
102 //diag_printf("Set SD Card in Transfer State.\n");
104 /*Put SD Card in Transfer State */
105 if (!mxcmci_trans_prepare()) {
107 if (sd_set_high_speed_mode()) {
112 if (sdmmc_set_blklen(BLK_LEN))
115 /* SD can only support 1/4 bit bitwidth, 8 bit is not supported */
116 if (EIGHT == bus_width) {
119 if (!sd_set_bus_width(bus_width)) {
120 esdhc_base_pointer->protocol_control &=
122 esdhc_base_pointer->protocol_control |=
123 (bus_width / 4) << 1;
124 diag_printf("Bus Width: %d\n",
132 diag_printf("Get CID Failed.\n");
136 //diag_printf("%s:failed to Init SD card!\n", __FUNCTION__);
141 cyg_uint32 sd_voltage_validation(void)
143 //wait max timeout (unit: ms)
144 cyg_uint32 timeout = 15000;
147 command_response_t response;
148 cyg_uint32 voltage_validation_command = 0;
149 cyg_uint32 default_rca = 0;
151 cyg_uint32 ocr_value = SD_OCR_VALUE_HV_LC; /* nirp_oct07: <- split OCR to 3.3v and 1.8v cases */
152 cyg_uint32 voltage_validation = FAIL;
153 cyg_uint32 interface_value = 0;
154 cyg_uint32 card_usable = SUCCESS;
156 /* Configure Command CMD8 to check for High capacity support */
158 mxcmci_cmd_config(&cmd, CMD8, SD_IF_HV_COND_ARG, READ, RESPONSE_48,
159 DATA_PRESENT_NONE, ENABLE, ENABLE);
161 /* Issue Command CMD8 to SD Memory card */
162 if (host_send_cmd(&cmd) == SUCCESS) { /* nirp_oct07: <- changed order of detection */
163 //diag_printf("%s:CMD8 OK!\n", __FUNCTION__);
164 response.format = RESPONSE_48;
165 host_read_response(&response);
167 /* Obtain Interface value from the response buffer */
168 interface_value = response.cmd_rsp0;
170 /* Check if volatge lies in range or not */
171 if ((interface_value & SD_IF_HV_COND_ARG) == SD_IF_HV_COND_ARG) {
172 ocr_value = ((cyg_uint32) (SD_OCR_VALUE_HV_HC) & 0xFFFFFFFF); /* nirp_oct07: <- split OCR to 3.3v and 1.8v cases */
175 /* start timer for a delay of 1.5sec, for ACMD41 */
178 while ((voltage_validation_command < 20)
179 && (voltage_validation != SUCCESS)
180 && (card_usable == SUCCESS)) {
181 /* Configure CMD55 for SD card */
182 /* This command expects defualt RCA 0x0000 as argument. */
183 mxcmci_cmd_config(&cmd, CMD55, default_rca, READ,
184 RESPONSE_48, DATA_PRESENT_NONE,
187 /* Issue CMD55 to SD Memory card */
188 if (host_send_cmd(&cmd) == FAIL) {
189 voltage_validation = FAIL;
190 //diag_printf("Send CMD55 Failed.\n");
193 /* Configure ACMD41 for SD card */
194 /* This command expects operating voltage range as argument. */
195 /* CODE REVIEW START: Need to check why BUSY was expected */
196 /* INTERNAL CODE REVIEW: Accepted - to fix original code if needed */
197 /* nirp: changed RESPONSE_48_CHECK_BUSY to RESPONSE_48 */
198 /* nirp_oct03: why with busy again? ACMD41 doesn't hold busy line */
199 mxcmci_cmd_config(&cmd, ACMD41, ocr_value, READ,
200 RESPONSE_48, DATA_PRESENT_NONE, DISABLE,
203 /* Issue ACMD41 to SD Memory card to determine OCR value */
204 if (host_send_cmd(&cmd) == FAIL) {
205 voltage_validation = FAIL;
206 diag_printf("Send CMD41 Failed.\n");
209 /* Read Response from CMDRSP0 Register */
210 response.format = RESPONSE_48;
211 host_read_response(&response);
213 /* Obtain OCR Values from the response */
214 /* Obtain OCR value from the response buffer */
215 ocr_value = response.cmd_rsp0;
217 /* Check if card busy bit is cleared or not */
218 if (!(response.cmd_rsp0 & CARD_BUSY_BIT)) {
219 /* Iterate One more time */
220 voltage_validation_command++;
223 /*CODE REVIEW START: Update code and check only bit 30, HC or LC card type. All voltage bits needs to be masked. */
224 /* INTERNAL CODE REVIEW: Accepted - need fix the code accordingly */
225 /* nirp: It may be better to check the actual power supply voltage - requiring the entire range (0xff8000) may fail the sequence even if the device can be supported */
226 /*CODE REVIEW END: */
228 if ((response.cmd_rsp0 & SD_OCR_HC_RES) == SD_OCR_HC_RES) {
229 address_mode = SECT_MODE;
230 voltage_validation = SUCCESS;
232 /* CODE REVIEW 3: (same as above) Check is logically correct, but seems redundent.
233 Anything that fails the HC check, is assumed Low Capacity */
234 /* nirp_oct03: this can be just an "else". the LC macro is 0 anyway,
235 and anything not HC is LC by default */
236 /* removed else if */
238 address_mode = BYTE_MODE;
239 voltage_validation = SUCCESS;
248 if (voltage_validation == FAIL) {
253 /*3.3v test failed, try to test 1.8v mode! */
254 mxcmci_cmd_config(&cmd, CMD8, SD_IF_LV_COND_ARG, READ,
255 RESPONSE_48, DATA_PRESENT_NONE, ENABLE,
258 /* Issue Command CMD8 to SD Memory card */
259 if (host_send_cmd(&cmd) == FAIL) {
260 //diag_printf("%s:CMD8 for 1.8v failed!\n", __FUNCTION__);
261 /* nirp_oct07: CMD8 failed both in 3.3 and in 1.8v, try SD 1.x case - no CMD8, LC, 3.3v only */
262 ocr_value = ((cyg_uint32) (SD_OCR_VALUE_HV_LC) & 0xFFFFFFFF); /* nirp_oct07: <- changed order of detection */
264 //diag_printf("%s:CMD8 for 1.8v OK!\n", __FUNCTION__);
265 response.format = RESPONSE_48;
266 host_read_response(&response);
268 /* Obtain Interface value from the response buffer */
269 interface_value = response.cmd_rsp0;
271 /* Check if volatge lies in range or not */
272 if ((interface_value & SD_IF_LV_COND_ARG) == SD_IF_LV_COND_ARG) {
273 ocr_value = ((cyg_uint32) (SD_OCR_VALUE_LV_HC) & 0xFFFFFFFF); /* nirp_oct07: <- split OCR to 3.3v and 1.8v cases */
275 /* nirp_oct07: otherwise, try with HV_LC settings (set at function start) */
280 /* start timer for a delay of 1.5sec, for ACMD41 */
283 /* nirp_oct03: MMCSD_READY_TIMEOUT too long.
284 ACMD41 also takes longer than CMD1 (twice - ~200 clocks for CMD55+resp+CMD41+resp */
285 /* In any case ,ACMD 41 will loop not more than 1.5 sec */
286 while ((voltage_validation_command < 20)
287 && (voltage_validation != SUCCESS) && (card_usable == SUCCESS)) {
288 /* Configure CMD55 for SD card */
289 /* This command expects defualt RCA 0x0000 as argument. */
290 mxcmci_cmd_config(&cmd, CMD55, default_rca, READ, RESPONSE_48,
291 DATA_PRESENT_NONE, ENABLE, ENABLE);
293 /* Issue CMD55 to SD Memory card */
294 if (host_send_cmd(&cmd) == FAIL) {
295 voltage_validation = FAIL;
296 //diag_printf("Send CMD55 Failed!\n");
299 /* Configure ACMD41 for SD card */
300 /* This command expects operating voltage range as argument. */
301 /* CODE REVIEW START: Need to check why BUSY was expected */
302 /* INTERNAL CODE REVIEW: Accepted - to fix original code if needed */
303 /* nirp: changed RESPONSE_48_CHECK_BUSY to RESPONSE_48 */
304 /* nirp_oct03: why with busy again? ACMD41 doesn't hold busy line */
305 mxcmci_cmd_config(&cmd, ACMD41, ocr_value, READ,
306 RESPONSE_48, DATA_PRESENT_NONE,
309 /* CODE REVIEW END: */
311 /* Issue ACMD41 to SD Memory card to determine OCR value */
312 if (host_send_cmd(&cmd) == FAIL) {
313 voltage_validation = FAIL;
314 diag_printf("Send ACMD41 Failed!\n");
317 /* Read Response from CMDRSP0 Register */
318 response.format = RESPONSE_48;
319 host_read_response(&response);
321 /* Obtain OCR Values from the response */
322 /* Obtain OCR value from the response buffer
324 ocr_value = response.cmd_rsp0;
326 /* Check if card busy bit is cleared or not */
327 if (!(response.cmd_rsp0 & CARD_BUSY_BIT)) {
328 /* Iterate One more time */
329 voltage_validation_command++;
331 /*CODE REVIEW START: Update code and check only bit 30, HC or LC card type. All voltage bits needs to be masked. */
332 /* INTERNAL CODE REVIEW: Accepted - need fix the code accordingly */
333 /* nirp: It may be better to check the actual power supply voltage - requiring the entire range (0xff8000) may fail the sequence even if the device can be supported */
334 /*CODE REVIEW END: */
336 if ((response.cmd_rsp0 & SD_OCR_HC_RES) == SD_OCR_HC_RES) {
337 address_mode = SECT_MODE;
338 voltage_validation = SUCCESS;
340 /* CODE REVIEW 3: (same as above) Check is logically correct, but seems redundent.
341 Anything that fails the HC check, is assumed Low Capacity */
342 /* nirp_oct03: this can be just an "else". the LC macro is 0 anyway,
343 and anything not HC is LC by default */
345 address_mode = BYTE_MODE;
346 voltage_validation = SUCCESS;
357 return voltage_validation;
360 static cyg_uint32 sd_get_rca(void)
363 cyg_uint32 card_state = 0;
364 cyg_uint32 rca_request = 0;
365 command_response_t response;
367 /* Configure CMD3 for MMC card */
368 /* 32bit card address is expected as Argument */
369 mxcmci_cmd_config(&cmd, CMD3, NO_ARG, READ, RESPONSE_48,
370 DATA_PRESENT_NONE, ENABLE, ENABLE);
372 /* Get relative address of the card */
374 if (host_send_cmd(&cmd) == FAIL) {
376 diag_printf("Send CMD3 Failed.\n");
378 /* Read Command response */
379 response.format = RESPONSE_48;
380 host_read_response(&response);
382 Card_rca = ((cyg_uint32) (response.cmd_rsp0 >> RCA_SHIFT));
384 card_state = CURR_CARD_STATE(response.cmd_rsp0);
386 if (card_state == IDENT) {
387 rca_request = SUCCESS;
390 diag_printf("Get RCA Failed.\n");
397 static cyg_uint32 sd_get_bit_mode_support(void)
400 cyg_uint32 rd_data_buff[128];
401 cyg_uint32 bit4_mode_support;
402 command_response_t response;
403 cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
405 /* Configure CMD55 for SD card */
406 /* This command expects RCA as argument. */
407 mxcmci_cmd_config(&cmd, CMD55, card_address, READ, RESPONSE_48,
408 DATA_PRESENT_NONE, ENABLE, ENABLE);
410 /* Issue CMD55 to SD Memory card */
411 if (host_send_cmd(&cmd) == FAIL) {
412 bit4_mode_support = 0;
414 /* Read Command response */
415 response.format = RESPONSE_48;
416 host_read_response(&response);
418 /* Afetr giving ACMD Command, the R1 response should have
421 if (response.cmd_rsp0 & SD_R1_STATUS_APP_CMD_MSK) {
423 /* Configure ACMD51 for SD card */
424 /* This command expects No argument. */
426 mxcmci_cmd_config(&cmd, ACMD51, NO_ARG, READ,
427 RESPONSE_48, DATA_PRESENT, ENABLE,
430 /* Issue ACMD51 to SD Memory card */
431 if (host_send_cmd(&cmd) == FAIL) {
432 bit4_mode_support = 0;
434 /* Read Response from e-SDHC buffer */
435 host_data_read(rd_data_buff, 512);
437 /* Check for bus width supported */
438 bit4_mode_support = (rd_data_buff[SD_BUS_WIDTH_OFFSET] & BIT_MODE_4_SUPPORT);
440 if (bit4_mode_support) {
441 bit4_mode_support = BIT_4_MODE;
448 return bit4_mode_support;
451 static cyg_uint32 sd_set_bus_width(cyg_uint32 bus_width)
454 cyg_uint32 set_bus_width_status = 0;
455 command_response_t response;
456 cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
458 if ((bus_width == FOUR) || (bus_width == ONE)) {
459 /* Configure CMD55 for SD card */
460 /* This command expects RCA as argument. */
462 mxcmci_cmd_config(&cmd, CMD55, card_address, READ, RESPONSE_48,
463 DATA_PRESENT_NONE, ENABLE, ENABLE);
465 /* Issue CMD55 to SD Memory card */
466 if (host_send_cmd(&cmd) == FAIL) {
467 set_bus_width_status = FAIL;
469 /* Read Command response */
470 response.format = RESPONSE_48;
471 host_read_response(&response);
473 /* Afetr giving ACMD Command, the R1 response should have
476 if (response.cmd_rsp0 & SD_R1_STATUS_APP_CMD_MSK) {
477 bus_width = (bus_width >> ONE);
479 /* Configure ACMD6 for SD card */
480 mxcmci_cmd_config(&cmd, ACMD6, bus_width, READ,
482 DATA_PRESENT_NONE, ENABLE,
485 /* Issue ACMD6 to SD Memory card */
486 if (host_send_cmd(&cmd) == FAIL) {
487 set_bus_width_status = FAIL;
489 set_bus_width_status = SUCCESS;
495 return set_bus_width_status;
498 /*==========================================================================
499 FUNCTION: cyg_uint32 sd_set_boot_partition (void)
501 sd_set_boot_partition() will set set boot partition for Partition1
512 Detailed Description:
514 ==============================================================================*/
516 cyg_uint32 esd_set_boot_partition(cyg_uint32 *src_ptr, cyg_uint32 length)
519 cyg_uint32 set_partition_status = FAIL;
520 command_response_t response;
521 cyg_uint8 response_data[512];
522 cyg_uint32 *response_pointer = (cyg_uint32 *) response_data;
523 cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
524 cyg_uint32 card_state;
526 /* Send CMD43 to select partition PARTITION1 active */
527 mxcmci_cmd_config(&cmd, CMD43,
535 if(host_send_cmd(&cmd) == FAIL) {
536 //diag_printf("%s: Send CMD43 Failed.\n", __FUNCTION__);
540 set_partition_status = mmc_data_write (src_ptr, length, 0);
541 if(set_partition_status) {
542 return 1; /* failed */
548 static cyg_uint32 sd_set_high_speed_mode(void)
551 cyg_uint32 status = FAIL;
552 command_response_t response;
554 /* Configure CMD6 for SD card */
555 mxcmci_cmd_config(&cmd, CMD6, 0xfffff1, READ, RESPONSE_48,
556 DATA_PRESENT_NONE, ENABLE, ENABLE);
558 /* Issue CMD6 to SD Memory card */
559 if (host_send_cmd(&cmd) == FAIL) {
561 diag_printf("Send CMD6 Failed.\n");
569 mxcmci_cmd_config(&cmd, CMD6, 0x80fffff1, READ, RESPONSE_48,
570 DATA_PRESENT_NONE, ENABLE, ENABLE);
572 /* Issue CMD6 to SD Memory card */
573 if (host_send_cmd(&cmd) == FAIL) {
575 diag_printf("Send CMD6 Failed.\n");
577 /* wait until in transfer mode */
578 while (mxcmci_trans_status()) {
588 /* end of mxcmic_sd.c */