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>
58 #include <cyg/hal/hal_soc.h>
59 #include <cyg/io/mxc_mmc.h>
61 static cyg_uint32 csd_get_value(void *csd, cyg_uint32 start_bit,
64 #define MMCSD_INIT_DELAY 64
66 cyg_uint32 Card_rca = 0x1; /* Relative Card Address */
67 card_ident Card_identification; /* Card Identification Data */
68 card_type Card_type; /* Card Type */
69 cyg_uint32 MMC_Spec_vers = 0x1; /* Spec vers used for MMC */
70 card_specific_data csd; /* Global variable for Card Specific Data */
71 cyg_uint32 Card_capacity_size = 0; /*Card capacity size */
72 cyg_uint32 CCC = 0; /* Card Command Class */
74 int HighCapacityCard = 0;
76 /*==========================================================================
78 ==========================================================================*/
80 cyg_uint32 mxcmci_init(cyg_uint32 bus_width, cyg_uint32 base_address)
82 cyg_uint32 init_status = FAIL;
84 flash_dprintf(FLASH_DEBUG_MAX, "%s:try to init base address...\n",
86 /* initialize Interface Controller */
87 host_init(base_address);
88 flash_dprintf(FLASH_DEBUG_MAX, "%s:try to software reset...\n",
91 /* Software Reset to Interface Controller */
92 host_reset(ESDHC_ONE_BIT_SUPPORT, ESDHC_LITTLE_ENDIAN_MODE);
93 flash_dprintf(FLASH_DEBUG_MAX, "%s:try to set identification freq...\n",
96 /* Enable Identification Frequency */
97 host_cfg_clock(IDENTIFICATION_FREQ);
99 /* Add delay of 2 msec, let mmc/sd card to initialize */
100 hal_delay_us(2 * 1000);
102 flash_dprintf(FLASH_DEBUG_MAX, "%s:try to software resetto card...\n",
105 //diag_printf("SW Reset...\n");
106 /* Issue Software Reset to card */
107 if (mxcmci_software_reset())
110 //diag_printf("Check Card...\n");
112 /* Check if the card is SD Memory Card */
113 if (!sd_voltage_validation()) {
114 flash_dprintf(FLASH_DEBUG_MAX, "%s:try to verify SD card...\n",
116 /* Call SD Initialization Function */
117 init_status = sd_init(bus_width);
119 ((csd.csd3 & CSD_STRUCT_MSK) ? SD_CSD_2_0 : SD_CSD_1_0);
121 /* Card Command Class */
122 CCC = csd_get_value(&csd, 84, 95);
124 flash_dprintf(FLASH_DEBUG_MAX, "%s:try to verify MMC card...\n",
126 /* Check if the card is MMC Memory Card */
127 if (!mmc_voltage_validation()) {
129 /* Call MMC Initialization Function */
130 init_status = mmc_init(bus_width);
132 Card_type = ((csd.csd3 & CSD_STRUCT_MSK) >> CSD_STRUCT_SHIFT) + SD_CSD_2_0;
133 MMC_Spec_vers = (csd.csd3 & MMC_CSD_SPEC_VERS_MASK) >> MMC_CSD_SPEC_VERS_SHIFT;
134 /* Card Command Class */
135 CCC = csd_get_value(&csd, 84, 95);
142 /*==========================================================================
143 FUNCTION: static cyg_uint32 card_get_csd (void)
145 this function will read MMC/SD CSD register and store in the global Variable.
159 Detailed Description:
160 1.Send CMD9 to get CSD value of MMC/SD Card.
161 2.Extract CSD value from CMDRSP0,CMDRSP1,CMDRSP2,CMDRSP3 registers.
162 ==============================================================================*/
163 cyg_uint32 card_get_csd(void)
167 command_response_t response;
168 cyg_uint32 status = FAIL;
169 cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
171 /* Configure CMD9 for MMC/SD card */
172 /* 16bit card address is expected as Argument */
173 mxcmci_cmd_config(&cmd, CMD9, card_address, READ, RESPONSE_136,
174 DATA_PRESENT_NONE, ENABLE, DISABLE);
176 /* Issue Command CMD9 to Extrace CSD register contents */
178 if (host_send_cmd(&cmd) != FAIL) {
179 /* Read Command response */
180 response.format = RESPONSE_136;
181 host_read_response(&response);
183 /* Assign Response to CSD Strcuture */
184 csd.csd0 = response.cmd_rsp0;
185 csd.csd1 = response.cmd_rsp1;
186 csd.csd2 = response.cmd_rsp2;
187 csd.csd3 = response.cmd_rsp3;
189 flash_dprintf(FLASH_DEBUG_MAX, "CSD:%x:%x:%x:%x\n", csd.csd0,
190 csd.csd1, csd.csd2, csd.csd3);
193 diag_printf("Get CSD Failed.\n");
200 static cyg_uint32 csd_get_value(void *csd, cyg_uint32 start_bit,
203 cyg_uint32 index = (start_bit / 32);
204 cyg_uint32 end_index = (end_bit / 32);
205 cyg_uint32 offset = (start_bit - 8) % 32;
206 cyg_uint32 end_offset = (end_bit - 8) % 32;
209 cyg_uint32 *pcsd = csd;
211 flash_dprintf(FLASH_DEBUG_MAX,
212 "start_bit=%d, end_bit=%d, index=%d, end_index=%d, offset=%d\n",
213 start_bit, end_bit, index, end_index, offset);
215 if (index == end_index) {
216 flash_dprintf(FLASH_DEBUG_MAX, "onl1y in index register\n");
218 (*((cyg_uint32 *) ((cyg_uint32) pcsd + (index << 2)))) &
219 ((1 << (end_offset + 1)) - (1 << offset));
220 value = (value >> offset);
222 flash_dprintf(FLASH_DEBUG_MAX, "index and index+1 registers\n");
224 *((cyg_uint32 *) ((cyg_uint32) pcsd +
225 (index << 2))) & (0xFFFFFFFF -
227 value = (value >> offset);
228 temp = (1 << (offset + end_bit - start_bit - 31)) - 1;
230 (*((cyg_uint32 *) ((cyg_uint32) pcsd + (index + 1) * 4)) &
232 value += temp << (32 - offset);
235 flash_dprintf(FLASH_DEBUG_MAX, "%s:value=%x (CSD:%x:%x:%x:%x)\n",
236 __FUNCTION__, value, *pcsd, *(pcsd + 1), *(pcsd + 2),
242 cyg_uint32 card_get_capacity_size(void)
244 cyg_uint32 capacity = 0;
245 cyg_uint32 c_size, c_size_mult, blk_len;
247 if (!csd.csd0 && !csd.csd1 && !csd.csd2 && !csd.csd3)
248 flash_dprintf(FLASH_DEBUG_MAX,
249 "WARNINGS:mxcmci_init should be done first!\n");
256 c_size = csd_get_value((void*)&csd, 62, 73);
257 c_size_mult = csd_get_value(&csd, 47, 49);
258 blk_len = csd_get_value(&csd, 80, 83);
259 capacity = (c_size + 1) << (c_size_mult + 2 + blk_len - 10);
262 //blk_len = csd_get_value(&csd, 80, 83);
263 c_size = csd_get_value(&csd, 48, 69);
264 capacity = (c_size + 1) * 512; /* block length is fixed to 512B */
271 /* check whether the card is high capacity card */
272 if(capacity>2*1024*1024)
273 HighCapacityCard = 1;
275 HighCapacityCard = 0;
281 cyg_uint32 mxcmci_data_read(cyg_uint32 * dest_ptr, cyg_uint32 len,
284 cyg_uint32 read_status = FAIL;
286 read_status = mmc_data_read(dest_ptr, len, offset);
295 cyg_uint32 mxcmci_software_reset(void)
298 cyg_uint32 response = FAIL;
300 /*Configure CMD0 for MMC/SD card */
301 /*CMD0 doesnt expect any response */
302 mxcmci_cmd_config(&cmd, CMD0, NO_ARG, READ, RESPONSE_NONE,
303 DATA_PRESENT_NONE, DISABLE, DISABLE);
305 /*Issue CMD0 to MMC/SD card to put in active state */
306 if (host_send_cmd(&cmd) != FAIL) {
309 diag_printf("Card SW Reset Failed.\n");
315 cyg_uint32 mxcmci_get_cid(void)
319 cyg_uint32 cid_request = FAIL;
320 command_response_t response;
322 /* Configure CMD2 for card */
323 /* No Argument is expected for CMD2 */
324 mxcmci_cmd_config(&cmd, CMD2, NO_ARG, READ, RESPONSE_136,
325 DATA_PRESENT_NONE, ENABLE, DISABLE);
327 /* Issue CMD2 to card to determine CID contents */
328 if (host_send_cmd(&cmd) == FAIL) {
330 diag_printf("Send CMD2 Failed.\n");
332 /* Read Command response */
333 response.format = RESPONSE_136;
334 host_read_response(&response);
336 /* Assign CID values to mmc_cid structures */
337 Card_identification.cid0 = response.cmd_rsp0;
338 Card_identification.cid1 = response.cmd_rsp1;
339 Card_identification.cid2 = response.cmd_rsp2;
340 Card_identification.cid3 = response.cmd_rsp3;
342 /* Assign cid_request as SUCCESS */
343 cid_request = SUCCESS;
346 flash_dprintf(FLASH_DEBUG_MAX, "%s:CID=%X:%X:%X:%X\n", __FUNCTION__,
347 Card_identification.cid0, Card_identification.cid1,
348 Card_identification.cid2, Card_identification.cid3);
352 cyg_uint32 mxcmci_trans_prepare(void)
355 cyg_uint32 card_state = 0;
356 cyg_uint32 transfer_status = 0;
357 command_response_t response;
358 cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
360 /* Configure CMD7 for MMC card */
361 /* 16bit card address is expected as Argument */
362 mxcmci_cmd_config(&cmd, CMD7, card_address, READ, RESPONSE_48,
363 DATA_PRESENT_NONE, ENABLE, ENABLE);
365 /* Sending the card from stand-by to transfer state */
366 if (host_send_cmd(&cmd) == FAIL) {
367 transfer_status = FAIL;
368 diag_printf("Send CMD7 Failed.\n");
371 /* Configure CMD13 to read status of the card becuase CMD7 has R1b response */
372 mxcmci_cmd_config(&cmd, CMD13, card_address, READ, RESPONSE_48,
373 DATA_PRESENT_NONE, ENABLE, ENABLE);
375 if (host_send_cmd(&cmd) == FAIL) {
376 transfer_status = FAIL;
377 diag_printf("Send CMD13 Failed.\n");
379 /* Read Command response */
380 response.format = RESPONSE_48;
381 host_read_response(&response);
383 card_state = CURR_CARD_STATE(response.cmd_rsp0);
385 if (card_state == TRAN) {
386 transfer_status = SUCCESS;
389 diag_printf("card_state: 0x%x\n", card_state);
390 transfer_status = FAIL;
396 return transfer_status;
400 cyg_uint32 mxcmci_trans_status(void)
403 cyg_uint32 card_state = 0;
404 cyg_uint32 transfer_status = 0;
405 command_response_t response;
406 cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
408 /* Configure CMD13 to read status of the card becuase CMD7 has R1b response */
409 mxcmci_cmd_config(&cmd, CMD13, card_address, READ, RESPONSE_48,
410 DATA_PRESENT_NONE, ENABLE, ENABLE);
412 if (host_send_cmd(&cmd) == FAIL) {
413 diag_printf("Fail, CMD13\n");
414 transfer_status = FAIL;
418 /* Read Command response */
419 response.format = RESPONSE_48;
420 host_read_response(&response);
422 card_state = CURR_CARD_STATE(response.cmd_rsp0);
424 if (card_state == TRAN) {
425 transfer_status = SUCCESS;
426 //diag_printf("card_state: 0x%x\n", card_state);
430 //diag_printf("card_state: 0x%x\n", card_state);
431 transfer_status = FAIL;
434 return transfer_status;
438 void mxcmci_cmd_config(command_t * cmd_config, cyg_uint32 index,
439 cyg_uint32 argument, xfer_type_t transfer,
440 response_format_t format, data_present_select data,
441 crc_check_enable crc, cmdindex_check_enable cmdindex)
446 /* Assign cmd to cmd_config */
449 /* Configure Command index */
450 cmd->command = index;
452 /* Configure Command Argument */
455 /* Configure Data transfer type */
456 cmd->data_transfer = transfer;
458 /* Configure Response Format */
459 cmd->response_format = format;
461 /* Configure Data Present Select */
462 cmd->data_present = data;
464 /* Configiure CRC check Enable */
465 cmd->crc_check = crc;
467 /*Configure Command index check enable */
468 cmd->cmdindex_check = cmdindex;
470 /* if multi-block is used */
471 if (CMD18 == index || CMD25 == index) {
472 /*Configure Block count enable */
473 cmd->block_count_enable_check = ENABLE;
474 /*Configure Multi single block select */
475 cmd->multi_single_block = MULTIPLE;
477 /*Configure Block count enable */
478 cmd->block_count_enable_check = DISABLE;
480 /*Configure Multi single block select */
481 cmd->multi_single_block = SINGLE;