]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/devs/flash/arm/mxc/v2_0/src/mxcmci_core.c
TX53 Release 2011-06-16
[karo-tx-redboot.git] / packages / devs / flash / arm / mxc / v2_0 / src / mxcmci_core.c
1 // ==========================================================================
2 //
3 //   mxcmci_core.c
4 //   (c) 2008, Freescale
5 //
6 //   MMC card driver for MXC platform
7 //
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.
13 //
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.
17 //
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
21 // for more details.
22 //
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.
26 //
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.
33 //
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.
36 //
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####
43 //
44 // Author(s):    Lewis Liu <weizhi.liu@freescale.com>
45 // Contributors: Lewis Liu <weizhi.liu@freescale.com>
46 // Date:         2008-05-13 Initial version
47 // Purpose:
48 // Description:
49 //
50 //####DESCRIPTIONEND####
51 //
52 //==========================================================================
53
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>
60
61 static cyg_uint32 csd_get_value(void *csd, cyg_uint32 start_bit,
62                                                                 cyg_uint32 end_bit);
63
64 #define MMCSD_INIT_DELAY 64
65
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 */
73 int Card_Mode = 2;
74 int HighCapacityCard = 0;
75
76 /*==========================================================================
77                                     Global FUNCTIONS
78 ==========================================================================*/
79
80 cyg_uint32 mxcmci_init(cyg_uint32 bus_width, cyg_uint32 base_address)
81 {
82         cyg_uint32 init_status = FAIL;
83
84         flash_dprintf(FLASH_DEBUG_MAX, "%s:try to init base address...\n",
85                                 __FUNCTION__);
86         /* initialize Interface Controller */
87         host_init(base_address);
88         flash_dprintf(FLASH_DEBUG_MAX, "%s:try to software reset...\n",
89                                 __FUNCTION__);
90
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",
94                                 __FUNCTION__);
95
96         /* Enable Identification Frequency */
97         host_cfg_clock(IDENTIFICATION_FREQ);
98
99         /* Add delay of 2 msec, let mmc/sd card to initialize */
100         hal_delay_us(2 * 1000);
101
102         flash_dprintf(FLASH_DEBUG_MAX, "%s:try to software resetto card...\n",
103                                 __FUNCTION__);
104
105         //diag_printf("SW Reset...\n");
106         /* Issue Software Reset to card */
107         if (mxcmci_software_reset())
108                 return FAIL;
109
110         //diag_printf("Check Card...\n");
111
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",
115                                         __FUNCTION__);
116                 /* Call SD Initialization Function */
117                 init_status = sd_init(bus_width);
118                 Card_type =
119                         ((csd.csd3 & CSD_STRUCT_MSK) ? SD_CSD_2_0 : SD_CSD_1_0);
120                 Card_Mode = 1;
121                 /* Card Command Class */
122                 CCC = csd_get_value(&csd, 84, 95);
123         } else {
124                 flash_dprintf(FLASH_DEBUG_MAX, "%s:try to verify MMC card...\n",
125                                         __FUNCTION__);
126                 /* Check if the card is MMC Memory Card */
127                 if (!mmc_voltage_validation()) {
128
129                         /* Call MMC Initialization Function */
130                         init_status = mmc_init(bus_width);
131                         Card_Mode = 0;
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);
136                 }
137         }
138
139         return init_status;
140 }
141
142 /*==========================================================================
143 FUNCTION: static cyg_uint32 card_get_csd (void)
144 DESCRIPTION:
145    this function will read MMC/SD CSD register and store in the global Variable.
146
147 ARGUMENTS PASSED:
148    None
149
150 RETURN VALUE:
151    cyg_uint32
152
153 PRE-CONDITIONS:
154    None
155
156 POST-CONDITIONS:
157    None
158
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)
164 {
165         command_t cmd;
166         command_response_t response;
167         cyg_uint32 status = FAIL;
168         cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
169
170         /* Configure CMD9 for MMC/SD card */
171         /* 16bit card address is expected as Argument */
172         mxcmci_cmd_config(&cmd, CMD9, card_address, READ, RESPONSE_136,
173                                         DATA_PRESENT_NONE, ENABLE, DISABLE);
174
175         /* Issue Command CMD9 to Extrace CSD register contents     */
176
177         if (host_send_cmd(&cmd) != FAIL) {
178                 /* Read Command response */
179                 response.format = RESPONSE_136;
180                 host_read_response(&response);
181
182                 /* Assign Response to CSD Strcuture */
183                 csd.csd0 = response.cmd_rsp0;
184                 csd.csd1 = response.cmd_rsp1;
185                 csd.csd2 = response.cmd_rsp2;
186                 csd.csd3 = response.cmd_rsp3;
187
188                 flash_dprintf(FLASH_DEBUG_MAX, "CSD:%x:%x:%x:%x\n", csd.csd0,
189                                         csd.csd1, csd.csd2, csd.csd3);
190                 status = SUCCESS;
191         } else {
192                 diag_printf("Get CSD Failed.\n");
193         }
194
195         return status;
196 }
197
198 static cyg_uint32 csd_get_value(void *csd, cyg_uint32 start_bit,
199                                                                 cyg_uint32 end_bit)
200 {
201         cyg_uint32 index = (start_bit / 32);
202         cyg_uint32 end_index = (end_bit / 32);
203         cyg_uint32 offset = (start_bit - 8) % 32;
204         cyg_uint32 end_offset = (end_bit - 8) % 32;
205         cyg_uint32 value;
206         cyg_uint32 temp;
207         cyg_uint32 *pcsd = csd;
208
209         flash_dprintf(FLASH_DEBUG_MAX,
210                                 "start_bit=%d, end_bit=%d, index=%d, end_index=%d, offset=%d\n",
211                                 start_bit, end_bit, index, end_index, offset);
212
213         if (index == end_index) {
214                 flash_dprintf(FLASH_DEBUG_MAX, "onl1y in index register\n");
215                 value =
216                         (*((cyg_uint32 *) ((cyg_uint32) pcsd + (index << 2)))) &
217                         ((1 << (end_offset + 1)) - (1 << offset));
218                 value = (value >> offset);
219         } else {
220                 flash_dprintf(FLASH_DEBUG_MAX, "index and index+1 registers\n");
221                 value =
222                         *((cyg_uint32 *) ((cyg_uint32) pcsd +
223                                                                 (index << 2))) & (0xFFFFFFFF -
224                                                                                                 (1 << offset) + 1);
225                 value = (value >> offset);
226                 temp = (1 << (offset + end_bit - start_bit - 31)) - 1;
227                 temp =
228                         (*((cyg_uint32 *) ((cyg_uint32) pcsd + (index + 1) * 4)) &
229                                 temp);
230                 value += temp << (32 - offset);
231         }
232
233         flash_dprintf(FLASH_DEBUG_MAX, "%s:value=%x (CSD:%x:%x:%x:%x)\n",
234                                 __FUNCTION__, value, *pcsd, *(pcsd + 1), *(pcsd + 2),
235                                 *(pcsd + 3));
236         return value;
237 }
238
239 cyg_uint32 card_get_capacity_size(void)
240 {
241         cyg_uint32 capacity = 0;
242         cyg_uint32 c_size, c_size_mult, blk_len;
243
244         if (!csd.csd0 && !csd.csd1 && !csd.csd2 && !csd.csd3)
245                 flash_dprintf(FLASH_DEBUG_MAX,
246                                         "WARNINGS:mxcmci_init should be done first!\n");
247
248         switch (Card_type) {
249         case SD_CSD_1_0:
250         case MMC_CSD_1_0:
251         case MMC_CSD_1_1:
252         case MMC_CSD_1_2:
253                 c_size = csd_get_value((void*)&csd, 62, 73);
254                 c_size_mult = csd_get_value(&csd, 47, 49);
255                 blk_len = csd_get_value(&csd, 80, 83);
256                 capacity = (c_size + 1) << (c_size_mult + 2 + blk_len - 10);
257                 break;
258         case SD_CSD_2_0:
259                 //blk_len = csd_get_value(&csd, 80, 83);
260                 c_size = csd_get_value(&csd, 48, 69);
261                 capacity = (c_size + 1) * 512;    /* block length is fixed to 512B */
262                 break;
263         default:
264                 capacity = 1;
265                 break;
266         }
267
268         /* check whether the card is high capacity card */
269         if(capacity>2*1024*1024)
270                 HighCapacityCard = 1;
271         else
272                 HighCapacityCard = 0;
273
274         return capacity;
275 }
276
277 cyg_uint32 mxcmci_data_read(cyg_uint32 *dest_ptr, cyg_uint32 len,
278                                                         cyg_uint32 offset)
279 {
280         cyg_uint32 read_status = FAIL;
281
282         read_status = mmc_data_read(dest_ptr, len, offset);
283
284         if (read_status) {
285                 len = 0;
286         }
287         return len;
288 }
289
290 cyg_uint32 mxcmci_software_reset(void)
291 {
292         command_t cmd;
293         cyg_uint32 response = FAIL;
294
295         /*Configure CMD0 for MMC/SD card */
296         /*CMD0 doesnt expect any response */
297         mxcmci_cmd_config(&cmd, CMD0, NO_ARG, READ, RESPONSE_NONE,
298                                         DATA_PRESENT_NONE, DISABLE, DISABLE);
299
300         /*Issue CMD0 to MMC/SD card to put in active state */
301         if (host_send_cmd(&cmd) != FAIL) {
302                 response = SUCCESS;
303         } else {
304                 diag_printf("Card SW Reset Failed.\n");
305         }
306
307         return response;
308 }
309
310 cyg_uint32 mxcmci_get_cid(void)
311 {
312
313         command_t cmd;
314         cyg_uint32 cid_request = FAIL;
315         command_response_t response;
316
317         /* Configure CMD2 for card */
318         /* No Argument is expected for CMD2 */
319         mxcmci_cmd_config(&cmd, CMD2, NO_ARG, READ, RESPONSE_136,
320                                         DATA_PRESENT_NONE, ENABLE, DISABLE);
321
322         /* Issue CMD2 to card to determine CID contents */
323         if (host_send_cmd(&cmd) == FAIL) {
324                 cid_request = FAIL;
325                 diag_printf("Send CMD2 Failed.\n");
326         } else {
327                 /* Read Command response  */
328                 response.format = RESPONSE_136;
329                 host_read_response(&response);
330
331                 /* Assign CID values to mmc_cid structures */
332                 Card_identification.cid0 = response.cmd_rsp0;
333                 Card_identification.cid1 = response.cmd_rsp1;
334                 Card_identification.cid2 = response.cmd_rsp2;
335                 Card_identification.cid3 = response.cmd_rsp3;
336
337                 /* Assign cid_request as SUCCESS */
338                 cid_request = SUCCESS;
339         }
340
341         flash_dprintf(FLASH_DEBUG_MAX, "%s:CID=%X:%X:%X:%X\n", __FUNCTION__,
342                                 Card_identification.cid0, Card_identification.cid1,
343                                 Card_identification.cid2, Card_identification.cid3);
344         return cid_request;
345 }
346
347 cyg_uint32 mxcmci_trans_prepare(void)
348 {
349         command_t cmd;
350         cyg_uint32 card_state = 0;
351         cyg_uint32 transfer_status = 0;
352         command_response_t response;
353         cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
354
355         /* Configure CMD7 for MMC card */
356         /* 16bit card address is expected as Argument */
357         mxcmci_cmd_config(&cmd, CMD7, card_address, READ, RESPONSE_48,
358                                         DATA_PRESENT_NONE, ENABLE, ENABLE);
359
360         /* Sending the card from stand-by to transfer state */
361         if (host_send_cmd(&cmd) == FAIL) {
362                 transfer_status = FAIL;
363                 diag_printf("Send CMD7 Failed.\n");
364         } else {
365
366                 /* Configure CMD13 to read status of the card becuase CMD7 has R1b response */
367                 mxcmci_cmd_config(&cmd, CMD13, card_address, READ, RESPONSE_48,
368                                                 DATA_PRESENT_NONE, ENABLE, ENABLE);
369
370                 if (host_send_cmd(&cmd) == FAIL) {
371                         transfer_status = FAIL;
372                         diag_printf("Send CMD13 Failed.\n");
373                 } else {
374                         /* Read Command response */
375                         response.format = RESPONSE_48;
376                         host_read_response(&response);
377
378                         card_state = CURR_CARD_STATE(response.cmd_rsp0);
379
380                         if (card_state == TRAN) {
381                                 transfer_status = SUCCESS;
382
383                         } else {
384                                 diag_printf("card_state: 0x%x\n", card_state);
385                                 transfer_status = FAIL;
386                         }
387                 }
388
389         }
390
391         return transfer_status;
392 }
393
394 cyg_uint32 mxcmci_trans_status(void)
395 {
396         command_t cmd;
397         cyg_uint32 card_state = 0;
398         cyg_uint32 transfer_status = 0;
399         command_response_t response;
400         cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
401
402         /* Configure CMD13 to read status of the card becuase CMD7 has R1b response */
403         mxcmci_cmd_config(&cmd, CMD13, card_address, READ, RESPONSE_48,
404                                         DATA_PRESENT_NONE, ENABLE, ENABLE);
405
406         if (host_send_cmd(&cmd) == FAIL) {
407                 diag_printf("Fail, CMD13\n");
408                 transfer_status = FAIL;
409         }
410
411         else {
412                 /* Read Command response */
413                 response.format = RESPONSE_48;
414                 host_read_response(&response);
415
416                 card_state = CURR_CARD_STATE(response.cmd_rsp0);
417
418                 if (card_state == TRAN) {
419                         transfer_status = SUCCESS;
420                         //diag_printf("card_state: 0x%x\n", card_state);
421                 }
422
423                 else {
424                         //diag_printf("card_state: 0x%x\n", card_state);
425                         transfer_status = FAIL;
426                 }
427         }
428         return transfer_status;
429 }
430
431 void mxcmci_cmd_config(command_t *cmd_config, cyg_uint32 index,
432                                         cyg_uint32 argument, xfer_type_t transfer,
433                                         response_format_t format, data_present_select data,
434                                         crc_check_enable crc, cmdindex_check_enable cmdindex)
435 {
436         command_t *cmd;
437
438         /* Assign cmd to cmd_config */
439         cmd = cmd_config;
440
441         /* Configure Command index */
442         cmd->command = index;
443
444         /* Configure Command Argument */
445         cmd->arg = argument;
446
447         /* Configure Data transfer type */
448         cmd->data_transfer = transfer;
449
450         /* Configure Response Format */
451         cmd->response_format = format;
452
453         /* Configure Data Present Select */
454         cmd->data_present = data;
455
456         /* Configiure CRC check Enable */
457         cmd->crc_check = crc;
458
459         /* Configure Command index check enable */
460         cmd->cmdindex_check = cmdindex;
461
462         /* if multi-block is used */
463         if (CMD18 == index || CMD25 == index) {
464                 /* Configure Block count enable */
465                 cmd->block_count_enable_check = ENABLE;
466                 /* Configure Multi single block select */
467                 cmd->multi_single_block = MULTIPLE;
468         } else {
469                 /* Configure Block count enable */
470                 cmd->block_count_enable_check = DISABLE;
471
472                 /* Configure Multi single block select */
473                 cmd->multi_single_block = SINGLE;
474         }
475 }