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/infra/diag.h>
55 #include <cyg/io/mxcmci_host.h>
56 #include <cyg/io/mxcmci_core.h>
57 #include <cyg/io/mxcmci_mmc.h>
59 static cyg_uint32 sd_get_rca(void);
60 static cyg_uint32 sd_get_bit_mode_support(void);
61 static cyg_uint32 sd_set_bus_width(cyg_uint32);
62 static cyg_uint32 sd_set_high_speed_mode(void);
64 #define SD_OCR_VALUE_HV_LC 0x00ff8000 /* nirp_oct07: <- 3.3v, LC */
65 #define SD_OCR_VALUE_HV_HC 0x40ff8000 /* nirp_oct07: <- 3.3v, HC */
66 /* nirp_oct07: LV_LC not needed - 1.8v is only supported under eSD which supports HC by default (SD>2.00) */
67 #define SD_OCR_VALUE_LV_HC 0x40000080 /* nirp_oct07: <- 1.8v, HC */
69 #define SD_OCR_HC_RES 0x40000000
70 #define SD_OCR_LC_RES 0x00000000
72 #define SD_IF_HV_COND_ARG 0x000001AA
73 #define SD_IF_LV_COND_ARG 0x000002AA
76 #define SD_R1_STATUS_APP_CMD_MSK 0x20
77 #define BIT_MODE_4_SUPPORT 5
78 #define SD_BUS_WIDTH_OFFSET 6
80 #define SD_STATUS_LEN 64
82 #define SD_BOOT_SWITCH_ARG 0x80FFFF2F
83 #define SD_PARTITION1 0x01000000
85 cyg_uint32 sd_init(cyg_uint32 bus_width)
87 cyg_uint32 status = FAIL;
88 cyg_uint32 bus_size = bus_width;
90 /* Get CID number of SD Memory Card */
91 if (!mxcmci_get_cid()) {
92 //diag_printf("%s:mxcmci_get_cid OK!\n", __FUNCTION__);
93 /* Set RCA of the SD Card */
95 //diag_printf("%s:sd_get_rca OK!\n", __FUNCTION__);
96 /*Get CSD from Card */
100 /*Enable operating frequency */
101 host_cfg_clock(OPERATING_FREQ);
103 //diag_printf("Set SD Card in Transfer State.\n");
105 /*Put SD Card in Transfer State */
106 if (!mxcmci_trans_prepare()) {
108 if (sd_set_high_speed_mode()) {
113 if (sdmmc_set_blklen(BLK_LEN))
116 /* SD can only support 1/4 bit bitwidth, 8 bit is not supported */
117 if (8 == bus_width) {
120 if (!sd_set_bus_width(bus_width)) {
121 esdhc_base_pointer->protocol_control &=
123 esdhc_base_pointer->protocol_control |=
124 (bus_width / 4) << 1;
125 diag_printf("Bus Width: %d\n",
133 diag_printf("Get CID Failed.\n");
137 //diag_printf("%s:failed to Init SD card!\n", __FUNCTION__);
142 cyg_uint32 sd_voltage_validation(void)
144 //wait max timeout (unit: ms)
145 cyg_uint32 timeout = 15000;
148 command_response_t response;
149 cyg_uint32 voltage_validation_command = 0;
150 cyg_uint32 default_rca = 0;
152 cyg_uint32 ocr_value = SD_OCR_VALUE_HV_LC; /* nirp_oct07: <- split OCR to 3.3v and 1.8v cases */
153 cyg_uint32 voltage_validation = FAIL;
154 cyg_uint32 interface_value = 0;
155 cyg_uint32 card_usable = SUCCESS;
157 /* Configure Command CMD8 to check for High capacity support */
159 mxcmci_cmd_config(&cmd, CMD8, SD_IF_HV_COND_ARG, READ, RESPONSE_48,
160 DATA_PRESENT_NONE, ENABLE, ENABLE);
162 /* Issue Command CMD8 to SD Memory card */
163 if (host_send_cmd(&cmd) == SUCCESS) { /* nirp_oct07: <- changed order of detection */
164 //diag_printf("%s:CMD8 OK!\n", __FUNCTION__);
165 response.format = RESPONSE_48;
166 host_read_response(&response);
168 /* Obtain Interface value from the response buffer */
169 interface_value = response.cmd_rsp0;
171 /* Check if volatge lies in range or not */
172 if ((interface_value & SD_IF_HV_COND_ARG) == SD_IF_HV_COND_ARG) {
173 ocr_value = ((cyg_uint32) (SD_OCR_VALUE_HV_HC) & 0xFFFFFFFF); /* nirp_oct07: <- split OCR to 3.3v and 1.8v cases */
176 /* start timer for a delay of 1.5sec, for ACMD41 */
179 while ((voltage_validation_command < 20)
180 && (voltage_validation != SUCCESS)
181 && (card_usable == SUCCESS)) {
182 /* Configure CMD55 for SD card */
183 /* This command expects defualt RCA 0x0000 as argument. */
184 mxcmci_cmd_config(&cmd, CMD55, default_rca, READ,
185 RESPONSE_48, DATA_PRESENT_NONE,
188 /* Issue CMD55 to SD Memory card */
189 if (host_send_cmd(&cmd) == FAIL) {
190 voltage_validation = FAIL;
191 //diag_printf("Send CMD55 Failed.\n");
194 /* Configure ACMD41 for SD card */
195 /* This command expects operating voltage range as argument. */
196 /* CODE REVIEW START: Need to check why BUSY was expected */
197 /* INTERNAL CODE REVIEW: Accepted - to fix original code if needed */
198 /* nirp: changed RESPONSE_48_CHECK_BUSY to RESPONSE_48 */
199 /* nirp_oct03: why with busy again? ACMD41 doesn't hold busy line */
200 mxcmci_cmd_config(&cmd, ACMD41, ocr_value, READ,
201 RESPONSE_48, DATA_PRESENT_NONE, DISABLE,
204 /* Issue ACMD41 to SD Memory card to determine OCR value */
205 if (host_send_cmd(&cmd) == FAIL) {
206 voltage_validation = FAIL;
207 diag_printf("Send CMD41 Failed.\n");
210 /* Read Response from CMDRSP0 Register */
211 response.format = RESPONSE_48;
212 host_read_response(&response);
214 /* Obtain OCR Values from the response */
215 /* Obtain OCR value from the response buffer */
216 ocr_value = response.cmd_rsp0;
218 /* Check if card busy bit is cleared or not */
219 if (!(response.cmd_rsp0 & CARD_BUSY_BIT)) {
220 /* Iterate One more time */
221 voltage_validation_command++;
224 /*CODE REVIEW START: Update code and check only bit 30, HC or LC card type. All voltage bits needs to be masked. */
225 /* INTERNAL CODE REVIEW: Accepted - need fix the code accordingly */
226 /* 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 */
227 /*CODE REVIEW END: */
229 if ((response.cmd_rsp0 & SD_OCR_HC_RES) == SD_OCR_HC_RES) {
230 address_mode = SECT_MODE;
231 voltage_validation = SUCCESS;
233 /* CODE REVIEW 3: (same as above) Check is logically correct, but seems redundent.
234 Anything that fails the HC check, is assumed Low Capacity */
235 /* nirp_oct03: this can be just an "else". the LC macro is 0 anyway,
236 and anything not HC is LC by default */
237 /* removed else if */
239 address_mode = BYTE_MODE;
240 voltage_validation = SUCCESS;
249 if (voltage_validation == FAIL) {
254 /*3.3v test failed, try to test 1.8v mode! */
255 mxcmci_cmd_config(&cmd, CMD8, SD_IF_LV_COND_ARG, READ,
256 RESPONSE_48, DATA_PRESENT_NONE, ENABLE,
259 /* Issue Command CMD8 to SD Memory card */
260 if (host_send_cmd(&cmd) == FAIL) {
261 //diag_printf("%s:CMD8 for 1.8v failed!\n", __FUNCTION__);
262 /* nirp_oct07: CMD8 failed both in 3.3 and in 1.8v, try SD 1.x case - no CMD8, LC, 3.3v only */
263 ocr_value = ((cyg_uint32) (SD_OCR_VALUE_HV_LC) & 0xFFFFFFFF); /* nirp_oct07: <- changed order of detection */
265 //diag_printf("%s:CMD8 for 1.8v OK!\n", __FUNCTION__);
266 response.format = RESPONSE_48;
267 host_read_response(&response);
269 /* Obtain Interface value from the response buffer */
270 interface_value = response.cmd_rsp0;
272 /* Check if volatge lies in range or not */
273 if ((interface_value & SD_IF_LV_COND_ARG) == SD_IF_LV_COND_ARG) {
274 ocr_value = ((cyg_uint32) (SD_OCR_VALUE_LV_HC) & 0xFFFFFFFF); /* nirp_oct07: <- split OCR to 3.3v and 1.8v cases */
276 /* nirp_oct07: otherwise, try with HV_LC settings (set at function start) */
281 /* start timer for a delay of 1.5sec, for ACMD41 */
284 /* nirp_oct03: MMCSD_READY_TIMEOUT too long.
285 ACMD41 also takes longer than CMD1 (twice - ~200 clocks for CMD55+resp+CMD41+resp */
286 /* In any case ,ACMD 41 will loop not more than 1.5 sec */
287 while ((voltage_validation_command < 20)
288 && (voltage_validation != SUCCESS) && (card_usable == SUCCESS)) {
289 /* Configure CMD55 for SD card */
290 /* This command expects defualt RCA 0x0000 as argument. */
291 mxcmci_cmd_config(&cmd, CMD55, default_rca, READ, RESPONSE_48,
292 DATA_PRESENT_NONE, ENABLE, ENABLE);
294 /* Issue CMD55 to SD Memory card */
295 if (host_send_cmd(&cmd) == FAIL) {
296 voltage_validation = FAIL;
297 //diag_printf("Send CMD55 Failed!\n");
300 /* Configure ACMD41 for SD card */
301 /* This command expects operating voltage range as argument. */
302 /* CODE REVIEW START: Need to check why BUSY was expected */
303 /* INTERNAL CODE REVIEW: Accepted - to fix original code if needed */
304 /* nirp: changed RESPONSE_48_CHECK_BUSY to RESPONSE_48 */
305 /* nirp_oct03: why with busy again? ACMD41 doesn't hold busy line */
306 mxcmci_cmd_config(&cmd, ACMD41, ocr_value, READ,
307 RESPONSE_48, DATA_PRESENT_NONE,
310 /* CODE REVIEW END: */
312 /* Issue ACMD41 to SD Memory card to determine OCR value */
313 if (host_send_cmd(&cmd) == FAIL) {
314 voltage_validation = FAIL;
315 diag_printf("Send ACMD41 Failed!\n");
318 /* Read Response from CMDRSP0 Register */
319 response.format = RESPONSE_48;
320 host_read_response(&response);
322 /* Obtain OCR Values from the response */
323 /* Obtain OCR value from the response buffer
325 ocr_value = response.cmd_rsp0;
327 /* Check if card busy bit is cleared or not */
328 if (!(response.cmd_rsp0 & CARD_BUSY_BIT)) {
329 /* Iterate One more time */
330 voltage_validation_command++;
332 /*CODE REVIEW START: Update code and check only bit 30, HC or LC card type. All voltage bits needs to be masked. */
333 /* INTERNAL CODE REVIEW: Accepted - need fix the code accordingly */
334 /* 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 */
335 /*CODE REVIEW END: */
337 if ((response.cmd_rsp0 & SD_OCR_HC_RES) == SD_OCR_HC_RES) {
338 address_mode = SECT_MODE;
339 voltage_validation = SUCCESS;
341 /* CODE REVIEW 3: (same as above) Check is logically correct, but seems redundent.
342 Anything that fails the HC check, is assumed Low Capacity */
343 /* nirp_oct03: this can be just an "else". the LC macro is 0 anyway,
344 and anything not HC is LC by default */
346 address_mode = BYTE_MODE;
347 voltage_validation = SUCCESS;
358 return voltage_validation;
361 static cyg_uint32 sd_get_rca(void)
364 cyg_uint32 card_state = 0;
365 cyg_uint32 rca_request = 0;
366 command_response_t response;
368 /* Configure CMD3 for MMC card */
369 /* 32bit card address is expected as Argument */
370 mxcmci_cmd_config(&cmd, CMD3, NO_ARG, READ, RESPONSE_48,
371 DATA_PRESENT_NONE, ENABLE, ENABLE);
373 /* Get relative address of the card */
375 if (host_send_cmd(&cmd) == FAIL) {
377 diag_printf("Send CMD3 Failed.\n");
379 /* Read Command response */
380 response.format = RESPONSE_48;
381 host_read_response(&response);
383 Card_rca = ((cyg_uint32) (response.cmd_rsp0 >> RCA_SHIFT));
385 card_state = CURR_CARD_STATE(response.cmd_rsp0);
387 if (card_state == IDENT) {
388 rca_request = SUCCESS;
391 diag_printf("Get RCA Failed.\n");
398 static cyg_uint32 sd_get_bit_mode_support(void)
401 cyg_uint32 rd_data_buff[128];
402 cyg_uint32 bit4_mode_support;
403 command_response_t response;
404 cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
406 /* Configure CMD55 for SD card */
407 /* This command expects RCA as argument. */
408 mxcmci_cmd_config(&cmd, CMD55, card_address, READ, RESPONSE_48,
409 DATA_PRESENT_NONE, ENABLE, ENABLE);
411 /* Issue CMD55 to SD Memory card */
412 if (host_send_cmd(&cmd) == FAIL) {
413 bit4_mode_support = 0;
415 /* Read Command response */
416 response.format = RESPONSE_48;
417 host_read_response(&response);
419 /* Afetr giving ACMD Command, the R1 response should have
422 if (response.cmd_rsp0 & SD_R1_STATUS_APP_CMD_MSK) {
424 /* Configure ACMD51 for SD card */
425 /* This command expects No argument. */
427 mxcmci_cmd_config(&cmd, ACMD51, NO_ARG, READ,
428 RESPONSE_48, DATA_PRESENT, ENABLE,
431 /* Issue ACMD51 to SD Memory card */
432 if (host_send_cmd(&cmd) == FAIL) {
433 bit4_mode_support = 0;
435 /* Read Response from e-SDHC buffer */
436 host_data_read(rd_data_buff, 512);
438 /* Check for bus width supported */
439 bit4_mode_support = (rd_data_buff[SD_BUS_WIDTH_OFFSET] & BIT_MODE_4_SUPPORT);
441 if (bit4_mode_support) {
442 bit4_mode_support = BIT_4_MODE;
449 return bit4_mode_support;
452 static cyg_uint32 sd_set_bus_width(cyg_uint32 bus_width)
455 cyg_uint32 set_bus_width_status = 0;
456 command_response_t response;
457 cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
459 if ((bus_width == 4) || (bus_width == 1)) {
460 /* Configure CMD55 for SD card */
461 /* This command expects RCA as argument. */
463 mxcmci_cmd_config(&cmd, CMD55, card_address, READ, RESPONSE_48,
464 DATA_PRESENT_NONE, ENABLE, ENABLE);
466 /* Issue CMD55 to SD Memory card */
467 if (host_send_cmd(&cmd) == FAIL) {
468 set_bus_width_status = FAIL;
470 /* Read Command response */
471 response.format = RESPONSE_48;
472 host_read_response(&response);
474 /* Afetr giving ACMD Command, the R1 response should have
477 if (response.cmd_rsp0 & SD_R1_STATUS_APP_CMD_MSK) {
478 bus_width = (bus_width >> ONE);
480 /* Configure ACMD6 for SD card */
481 mxcmci_cmd_config(&cmd, ACMD6, bus_width, READ,
483 DATA_PRESENT_NONE, ENABLE,
486 /* Issue ACMD6 to SD Memory card */
487 if (host_send_cmd(&cmd) == FAIL) {
488 set_bus_width_status = FAIL;
490 set_bus_width_status = SUCCESS;
496 return set_bus_width_status;
499 /*==========================================================================
500 FUNCTION: cyg_uint32 sd_set_boot_partition (void)
502 sd_set_boot_partition() will set set boot partition for Partition1
513 Detailed Description:
515 ==============================================================================*/
517 cyg_uint32 esd_set_boot_partition(cyg_uint32 *src_ptr, cyg_uint32 length)
520 cyg_uint32 set_partition_status = FAIL;
521 command_response_t response;
522 cyg_uint8 response_data[512];
523 cyg_uint32 *response_pointer = (cyg_uint32 *) response_data;
524 cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
525 cyg_uint32 card_state;
527 /* Send CMD43 to select partition PARTITION1 active */
528 mxcmci_cmd_config(&cmd, CMD43,
536 if(host_send_cmd(&cmd) == FAIL) {
537 //diag_printf("%s: Send CMD43 Failed.\n", __FUNCTION__);
541 set_partition_status = mmc_data_write (src_ptr, length, 0);
542 if(set_partition_status) {
543 return 1; /* failed */
549 static cyg_uint32 sd_set_high_speed_mode(void)
552 cyg_uint32 status = FAIL;
553 command_response_t response;
555 /* Configure CMD6 for SD card */
556 mxcmci_cmd_config(&cmd, CMD6, 0xfffff1, READ, RESPONSE_48,
557 DATA_PRESENT_NONE, ENABLE, ENABLE);
559 /* Issue CMD6 to SD Memory card */
560 if (host_send_cmd(&cmd) == FAIL) {
562 diag_printf("Send CMD6 Failed.\n");
570 mxcmci_cmd_config(&cmd, CMD6, 0x80fffff1, READ, RESPONSE_48,
571 DATA_PRESENT_NONE, ENABLE, ENABLE);
573 /* Issue CMD6 to SD Memory card */
574 if (host_send_cmd(&cmd) == FAIL) {
576 diag_printf("Send CMD6 Failed.\n");
578 /* wait until in transfer mode */
579 while (mxcmci_trans_status()) {
589 /* end of mxcmic_sd.c */