]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/flash/arm/mxc/v2_0/src/mxcmci_sd.c
Initial revision
[karo-tx-redboot.git] / packages / devs / flash / arm / mxc / v2_0 / src / mxcmci_sd.c
1 // ==========================================================================
2 //
3 //   mxcmci_sd.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/io/mxcmci_host.h>
55 #include <cyg/io/mxcmci_core.h>
56 #include <cyg/io/mxcmci_mmc.h>
57
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);
62
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 */
67
68 #define SD_OCR_HC_RES 0x40000000
69 #define SD_OCR_LC_RES 0x00000000
70
71 #define SD_IF_HV_COND_ARG 0x000001AA
72 #define SD_IF_LV_COND_ARG 0x000002AA
73
74 #define RCA_SHIFT 16
75 #define SD_R1_STATUS_APP_CMD_MSK 0x20
76 #define BIT_MODE_4_SUPPORT 5
77 #define SD_BUS_WIDTH_OFFSET 6
78 #define BIT_4_MODE 4
79 #define SD_STATUS_LEN 64
80
81 #define SD_BOOT_SWITCH_ARG 0x80FFFF2F
82 #define SD_PARTITION1 0x01000000
83
84 cyg_uint32 sd_init(cyg_uint32 bus_width)
85 {
86     cyg_uint32 status = FAIL;
87     cyg_uint32 bus_size = bus_width;
88
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 */
93         if (!sd_get_rca()) {
94             //diag_printf("%s:sd_get_rca OK!\n", __FUNCTION__);
95             /*Get CSD from Card */
96             if (card_get_csd())
97                 return FAIL;
98
99             /*Enable operating frequency */
100             host_cfg_clock(OPERATING_FREQ);
101
102             //diag_printf("Set SD Card in Transfer State.\n");
103
104             /*Put SD Card in Transfer State */
105             if (!mxcmci_trans_prepare()) {
106 #if 0
107                 if (sd_set_high_speed_mode()) {
108                     return FAIL;
109                 }
110 #endif
111
112                 if (sdmmc_set_blklen(BLK_LEN))
113                     return FAIL;
114
115                 /* SD can only support 1/4 bit bitwidth, 8 bit is not supported */
116                 if (EIGHT == bus_width) {
117                     bus_width = FOUR;
118                 }
119                 if (!sd_set_bus_width(bus_width)) {
120                     esdhc_base_pointer->protocol_control &=
121                         ~(0x3 << 1);
122                     esdhc_base_pointer->protocol_control |=
123                         (bus_width / 4) << 1;
124                     diag_printf("Bus Width:    %d\n",
125                             bus_width);
126                     status = SUCCESS;
127                 }
128             }
129         }
130
131     } else {
132         diag_printf("Get CID Failed.\n");
133
134     }
135
136     //diag_printf("%s:failed to Init SD card!\n", __FUNCTION__);
137     return status;
138
139 }
140
141 cyg_uint32 sd_voltage_validation(void)
142 {
143     //wait max timeout (unit: ms)
144     cyg_uint32 timeout = 15000;
145
146     command_t cmd;
147     command_response_t response;
148     cyg_uint32 voltage_validation_command = 0;
149     cyg_uint32 default_rca = 0;
150
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;
155
156     /* Configure Command CMD8 to check for High capacity support */
157     /* try 3.3V first */
158     mxcmci_cmd_config(&cmd, CMD8, SD_IF_HV_COND_ARG, READ, RESPONSE_48,
159               DATA_PRESENT_NONE, ENABLE, ENABLE);
160
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);
166
167         /* Obtain Interface value from the response buffer */
168         interface_value = response.cmd_rsp0;
169
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 */
173         }
174
175         /* start timer for a  delay of 1.5sec, for ACMD41 */
176         hal_delay_us(1500);
177
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,
185                       ENABLE, ENABLE);
186
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");
191                 break;
192             } else {
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,
201                           DISABLE);
202
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");
207                     break;
208                 } else {
209                     /* Read Response from CMDRSP0 Register */
210                     response.format = RESPONSE_48;
211                     host_read_response(&response);
212
213                     /* Obtain OCR Values from the response */
214                     /* Obtain OCR value from the response buffer */
215                     ocr_value = response.cmd_rsp0;
216
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++;
221                     } else {
222
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: */
227
228                         if ((response.cmd_rsp0 & SD_OCR_HC_RES) == SD_OCR_HC_RES) {
229                             address_mode = SECT_MODE;
230                             voltage_validation = SUCCESS;
231                         }
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 */
237                         else {
238                             address_mode = BYTE_MODE;
239                             voltage_validation = SUCCESS;
240                         }
241                     }
242                 }
243             }
244
245             hal_delay_us(1000);
246         }
247
248         if (voltage_validation == FAIL) {
249             card_usable = FAIL;
250         }
251
252     } else {
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,
256                   ENABLE);
257
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 */
263         } else {
264             //diag_printf("%s:CMD8 for 1.8v OK!\n", __FUNCTION__);
265             response.format = RESPONSE_48;
266             host_read_response(&response);
267
268             /* Obtain Interface value from the response buffer */
269             interface_value = response.cmd_rsp0;
270
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 */
274             }
275             /* nirp_oct07: otherwise, try with HV_LC settings (set at function start) */
276         }
277
278     }
279
280     /* start timer for a  delay of 1.5sec, for ACMD41 */
281     hal_delay_us(1500);
282
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);
292
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");
297             break;
298         } else {
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,
307                       DISABLE, DISABLE);
308
309             /* CODE REVIEW END:  */
310
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");
315                 break;
316             } else {
317                 /* Read Response from CMDRSP0 Register */
318                 response.format = RESPONSE_48;
319                 host_read_response(&response);
320
321                 /* Obtain OCR Values from the response */
322                 /* Obtain OCR value from the response buffer
323                  */
324                 ocr_value = response.cmd_rsp0;
325
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++;
330                 } else {
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: */
335
336                     if ((response.cmd_rsp0 & SD_OCR_HC_RES) == SD_OCR_HC_RES) {
337                         address_mode = SECT_MODE;
338                         voltage_validation = SUCCESS;
339                     }
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 */
344                     else {
345                         address_mode = BYTE_MODE;
346                         voltage_validation = SUCCESS;
347                     }
348                 }
349             }
350
351         }
352
353         hal_delay_us(1000);
354
355     }
356
357     return voltage_validation;
358 }
359
360 static cyg_uint32 sd_get_rca(void)
361 {
362     command_t cmd;
363     cyg_uint32 card_state = 0;
364     cyg_uint32 rca_request = 0;
365     command_response_t response;
366
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);
371
372     /* Get relative address of the card     */
373
374     if (host_send_cmd(&cmd) == FAIL) {
375         rca_request = FAIL;
376         diag_printf("Send CMD3 Failed.\n");
377     } else {
378         /* Read Command response */
379         response.format = RESPONSE_48;
380         host_read_response(&response);
381
382         Card_rca = ((cyg_uint32) (response.cmd_rsp0 >> RCA_SHIFT));
383
384         card_state = CURR_CARD_STATE(response.cmd_rsp0);
385
386         if (card_state == IDENT) {
387             rca_request = SUCCESS;
388         } else {
389             rca_request = FAIL;
390             diag_printf("Get RCA Failed.\n");
391         }
392     }
393
394     return rca_request;
395 }
396
397 static cyg_uint32 sd_get_bit_mode_support(void)
398 {
399     command_t cmd;
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);
404
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);
409
410     /* Issue CMD55 to SD Memory card */
411     if (host_send_cmd(&cmd) == FAIL) {
412         bit4_mode_support = 0;
413     } else {
414         /* Read Command response */
415         response.format = RESPONSE_48;
416         host_read_response(&response);
417
418         /* Afetr giving ACMD Command, the R1 response should have
419          * STATUS_APP_CMD set
420          */
421         if (response.cmd_rsp0 & SD_R1_STATUS_APP_CMD_MSK) {
422
423             /* Configure ACMD51 for SD card */
424             /* This command expects No argument. */
425
426             mxcmci_cmd_config(&cmd, ACMD51, NO_ARG, READ,
427                       RESPONSE_48, DATA_PRESENT, ENABLE,
428                       ENABLE);
429
430             /* Issue ACMD51 to SD Memory card */
431             if (host_send_cmd(&cmd) == FAIL) {
432                 bit4_mode_support = 0;
433             } else {
434                 /* Read Response from e-SDHC buffer */
435                 host_data_read(rd_data_buff, 512);
436
437                 /* Check for bus width supported */
438                 bit4_mode_support = (rd_data_buff[SD_BUS_WIDTH_OFFSET] & BIT_MODE_4_SUPPORT);
439
440                 if (bit4_mode_support) {
441                     bit4_mode_support = BIT_4_MODE;
442                 }
443
444             }
445         }
446     }
447
448     return bit4_mode_support;
449 }
450
451 static cyg_uint32 sd_set_bus_width(cyg_uint32 bus_width)
452 {
453     command_t cmd;
454     cyg_uint32 set_bus_width_status = 0;
455     command_response_t response;
456     cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
457
458     if ((bus_width == FOUR) || (bus_width == ONE)) {
459         /* Configure CMD55 for SD card */
460         /* This command expects RCA as argument. */
461
462         mxcmci_cmd_config(&cmd, CMD55, card_address, READ, RESPONSE_48,
463                   DATA_PRESENT_NONE, ENABLE, ENABLE);
464
465         /* Issue CMD55 to SD Memory card */
466         if (host_send_cmd(&cmd) == FAIL) {
467             set_bus_width_status = FAIL;
468         } else {
469             /* Read Command response */
470             response.format = RESPONSE_48;
471             host_read_response(&response);
472
473             /* Afetr giving ACMD Command, the R1 response should have
474              * STATUS_APP_CMD set
475              */
476             if (response.cmd_rsp0 & SD_R1_STATUS_APP_CMD_MSK) {
477                 bus_width = (bus_width >> ONE);
478
479                 /* Configure ACMD6 for SD card */
480                 mxcmci_cmd_config(&cmd, ACMD6, bus_width, READ,
481                           RESPONSE_48,
482                           DATA_PRESENT_NONE, ENABLE,
483                           ENABLE);
484
485                 /* Issue ACMD6 to SD Memory card */
486                 if (host_send_cmd(&cmd) == FAIL) {
487                     set_bus_width_status = FAIL;
488                 } else {
489                     set_bus_width_status = SUCCESS;
490                 }
491             }
492         }
493     }
494
495     return set_bus_width_status;
496 }
497
498 /*==========================================================================
499 FUNCTION: cyg_uint32 sd_set_boot_partition (void)
500 DESCRIPTION:
501   sd_set_boot_partition() will set set boot partition for Partition1
502
503 RETURN VALUE:
504    SUCCESS / FAILURE
505
506 PRE-CONDITIONS:
507    None
508
509 POST-CONDITIONS:
510    None
511
512 Detailed Description:
513
514 ==============================================================================*/
515
516 cyg_uint32 esd_set_boot_partition(cyg_uint32 *src_ptr, cyg_uint32 length)
517 {
518     command_t cmd;
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;
525
526    /* Send CMD43 to select partition PARTITION1 active */
527     mxcmci_cmd_config(&cmd, CMD43,
528                               0x1<<24,
529                               READ,
530                               RESPONSE_48,
531                               DATA_PRESENT_NONE,
532                               ENABLE,
533                               ENABLE);
534
535     if(host_send_cmd(&cmd) == FAIL) {
536         //diag_printf("%s: Send CMD43 Failed.\n", __FUNCTION__);
537         return 1;
538     }
539
540     set_partition_status = mmc_data_write (src_ptr, length, 0);
541     if(set_partition_status) {
542         return 1; /* failed */
543     }
544
545     return 0;
546 }
547
548 static cyg_uint32 sd_set_high_speed_mode(void)
549 {
550     command_t cmd;
551     cyg_uint32 status = FAIL;
552     command_response_t response;
553
554     /* Configure CMD6 for SD card */
555     mxcmci_cmd_config(&cmd, CMD6, 0xfffff1, READ, RESPONSE_48,
556               DATA_PRESENT_NONE, ENABLE, ENABLE);
557
558     /* Issue CMD6 to SD Memory card */
559     if (host_send_cmd(&cmd) == FAIL) {
560         status = FAIL;
561         diag_printf("Send CMD6 Failed.\n");
562         return FAIL;
563     } else {
564         hal_delay_us(1000);
565         status = SUCCESS;
566
567     }
568
569     mxcmci_cmd_config(&cmd, CMD6, 0x80fffff1, READ, RESPONSE_48,
570               DATA_PRESENT_NONE, ENABLE, ENABLE);
571
572     /* Issue CMD6 to SD Memory card */
573     if (host_send_cmd(&cmd) == FAIL) {
574         status = FAIL;
575         diag_printf("Send CMD6 Failed.\n");
576     } else {
577         /* wait until in transfer mode */
578         while (mxcmci_trans_status()) {
579             hal_delay_us(5);
580         }
581
582         status = SUCCESS;
583     }
584
585     return status;
586 }
587
588 /* end of mxcmic_sd.c */