]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/flash/arm/mxc/v2_0/src/card_mx32.c
Initial revision
[karo-tx-redboot.git] / packages / devs / flash / arm / mxc / v2_0 / src / card_mx32.c
1 // ==========================================================================
2 //
3 //   card_mx32.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):    Ivan Xu <yu.xu@freescale.com>
45 // Contributors: Ivan Xu <yu.xu@freescale.com>
46 // Date:         2008-06-13 Initial version
47 // Purpose:
48 // Description:
49 //     Support SD/MMC cards based on SDHC controller.
50 //     only base functionality is implemented: Card init, read, write and erase.
51 //     Write protection are not supported so far.
52 //
53 //####DESCRIPTIONEND####
54 //
55 //==========================================================================
56
57 #include <cyg/io/card_mx32.h>
58 #include <cyg/hal/hal_io.h>
59 #include <redboot.h>
60 #include <stdlib.h>
61
62 //#define diag_printf1    diag_printf
63 #define diag_printf1(fmt,args...)
64
65 volatile psdhc_t pSDHC;
66 card_mode_t Card_Mode;
67 cyg_uint32 HighCapacityCard = 0;
68 cyg_uint32 card_address;
69 card_type  Card_type;            /* Card Type*/
70 CARD_ID card_id;
71 CARD_SPECIFIC_DATA csd;          /* Global variable for Card Specific Data */
72 cyg_uint32 CCC = 0;              /* Card Command Class */
73
74 static struct csd_v1_0 g_csd_val;
75
76 static void configure_cmd (command_t *cmd,cyg_uint32 index, cyg_uint32 argument,
77                                 cyg_uint32 transfer,cyg_uint32 response_format, cyg_uint32 data_enable,
78                                 cyg_uint32 bus_width )
79 {
80         /* Configure Command index */
81         cmd->index = index;
82
83         /* Configure Command argument */
84         cmd->arg = argument;
85         /* workaround for CMD0, send 80 clock cycles before CMD0 */
86         if (cmd->index == 0)
87         {
88                 cmd->data_control = (((transfer) << SDHC_CMD_WRITE_READ_SHIFT) |
89                         ((response_format) << SDHC_CMD_FROMAT_OF_RESP_SHIFT) |
90                         ((data_enable) << SDHC_CMD_DATA_ENABLE_SHIFT) |
91                         ((bus_width) << SDHC_CMD_BUS_WIDTH_SHIFT)) |
92                         (0x1 << SDHC_CMD_INIT_SHIFT );
93         } else {
94                 cmd->data_control = (((transfer) << SDHC_CMD_WRITE_READ_SHIFT) |
95                         ((response_format) << SDHC_CMD_FROMAT_OF_RESP_SHIFT) |
96                         ((data_enable) << SDHC_CMD_DATA_ENABLE_SHIFT) |
97                         ((bus_width) << SDHC_CMD_BUS_WIDTH_SHIFT));
98         }
99 }
100
101 static void stop_clk(void)
102 {
103         /* Stop the clock */
104 //      pSDHC->sdhc_clk = SDHC_CLK_STOP;
105
106         /* Wait till the clock has stopped */
107 //      while((pSDHC->sdhc_status & SDHC_STATUS_CARD_BUS_CLK_RUN_MSK));
108         return;
109 }
110
111 static void start_clk(void)
112 {
113         /* Start the clock */
114         pSDHC->sdhc_clk = SDHC_CLK_START;
115
116         /* Wait till the clock has started */
117         while(!(pSDHC->sdhc_status & SDHC_STATUS_CARD_BUS_CLK_RUN_MSK));
118         return;
119 }
120
121 static void configure_clk(frequency_mode_t mode)
122 {
123         if(mode == iden_mode)
124         {
125                 /* Below 400 kHz  */
126                 pSDHC->sdhc_clk_rate = 0x207;
127         }
128         else if(mode == trans_mode)
129         {
130                 /* Below 20 MHz  */
131                 pSDHC->sdhc_clk_rate = 0x3;
132         }
133
134     diag_printf1("pSDHC->sdhc_clk_rate=0x%x\n", pSDHC->sdhc_clk_rate);
135 }
136
137 static void read_response(cyg_uint32 response_mode, response_t*response)
138 {
139         cyg_uint32 resp1=0;
140         cyg_uint32 resp2=0;
141         cyg_uint32 resp3=0;
142         cyg_uint32 count;
143
144         if(response_mode != 0)
145         {
146                 if((response_mode == RESPONSE_48_CRC) || (response_mode == RESPONSE_48_WITHOUT_CRC))
147                 {
148                         resp1 = readl(0x50004000 + 0x34) & 0xffff;
149                         resp2 = readl(0x50004000 + 0x34) & 0xffff;
150                         resp3 = readl(0x50004000 + 0x34) & 0xffff;
151
152                         response->rsp0 = (resp1 << 24) | (resp2 << 8) | (resp3 >> 8);
153                 }
154                 else if(response_mode == RESPONSE_136)
155                 {
156                         resp1 = pSDHC->sdhc_res_fifo & 0xffff;
157                         resp2 = pSDHC->sdhc_res_fifo & 0xffff;
158                         response->rsp3 = (resp1 << 16) | resp2;
159                         resp1 = pSDHC->sdhc_res_fifo & 0xffff;
160                         resp2 = pSDHC->sdhc_res_fifo & 0xffff;
161                         response->rsp2 = (resp1 << 16) | resp2;
162
163                         resp1 = pSDHC->sdhc_res_fifo & 0xffff;
164                         resp2 = pSDHC->sdhc_res_fifo & 0xffff;
165                         response->rsp1 = (resp1 << 16) | resp2;
166
167                         resp1 = pSDHC->sdhc_res_fifo & 0xffff;
168                         resp2= pSDHC->sdhc_res_fifo & 0xffff;
169                         response->rsp0 = (resp1 << 16) | resp2;
170                 }
171
172                 /* Stop the clock */
173                 stop_clk();
174                 /* Clear w1c bits from STATUS register */
175                 pSDHC->sdhc_status |= SDHC_STATUS_CLEAR;
176         }
177
178         //return status;
179 }
180
181 static cyg_uint32 check_response(void)
182 {
183         cyg_uint32 status = PASS;
184
185         if((pSDHC->sdhc_status & SDHC_STATUS_END_CMD_RESP_MSK) &&
186            !(pSDHC->sdhc_status & SDHC_STATUS_TIME_OUT_RESP_MSK) &&
187            !(pSDHC->sdhc_status & SDHC_STATUS_RESP_CRC_ERR_MSK))
188         {
189                 status = PASS;
190         }
191         else
192         {
193                 status = FAIL;
194                 diag_printf("response status:  %x Fail!\n", pSDHC->sdhc_status);
195         }
196         return status;
197 }
198
199 static cyg_uint32 send_cmd_and_wait_resp(command_t *cmd)
200 {
201         /* Clear Interrupt status Register  and enable int*/
202         pSDHC->sdhc_status = 0xFFFFFFFF;
203         pSDHC->sdhc_int_cntr = SDHC_INT;
204
205         /* Write command index */
206         pSDHC->sdhc_cmd = cmd->index;
207
208         /* Write command arg */
209         pSDHC->sdhc_arg = cmd->arg;
210
211         /* Write command data control */
212         pSDHC->sdhc_dat_cont = cmd->data_control;
213
214         /* Start clock */
215         start_clk();
216
217         /* Wait for the response of command end */
218         while(!(pSDHC->sdhc_status & SDHC_STATUS_END_CMD_RESP_MSK) );
219
220         /* Mask all interrupts */
221         pSDHC->sdhc_int_cntr = 0;
222
223         /* Check if an error occured */
224         return check_response();
225 }
226
227 static cyg_uint32 card_get_csd (void)
228 {
229         command_t cmd;
230         response_t response;
231         cyg_uint32 status = FAIL;
232         //cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
233
234         /* Configure CMD9 for MMC/SD card */
235         /* 16bit card address is expected as Argument */
236         configure_cmd(&cmd,CMD9,card_address,READ,RESPONSE_136, DISABLE, ONE);
237
238         /* Send Command CMD9 to Extrace CSD register contents  */
239         if(send_cmd_and_wait_resp(&cmd) != FAIL)
240         {
241                 /* Read Command response */
242                 read_response (RESPONSE_136, &response);
243                 /* Assign Response to CSD Strcuture */
244                 csd.csd0 = response.rsp0;
245                 csd.csd1 = response.rsp1;
246                 csd.csd2 = response.rsp2;
247                 csd.csd3 = response.rsp3;
248                 diag_printf1("CSD:%x:%x:%x:%x\n", csd.csd0, csd.csd1, csd.csd2, csd.csd3);
249                 status = SUCCESS;
250         // save csd
251         memcpy(&g_csd_val, &csd, sizeof(struct csd_v1_0));
252         diag_printf1("g_csd_val.c_size_mult=0x%x\n", g_csd_val.c_size_mult);
253         diag_printf1("g_csd_val addr=%p\n", &g_csd_val);
254         }
255
256         return status;
257 }
258
259 static cyg_uint32 csd_get_value(CARD_SPECIFIC_DATA * pcsd, cyg_uint32 start_bit, cyg_uint32 end_bit)
260 {
261         cyg_uint32 value;
262     if (start_bit == 84) {
263         value = g_csd_val.ccc;
264     } else if (start_bit == 62) {
265         value = (g_csd_val.c_size_up << 2) | g_csd_val.c_size_lo;
266     } else if (start_bit == 47) {
267         value = g_csd_val.c_size_mult;
268     } else if (start_bit == 80) {
269         value = g_csd_val.read_bl_len;
270     } else if (start_bit == 48) {
271         struct csd_v2_0 *ptr = (struct csd_v2_0 *) &g_csd_val;
272         value = (ptr->c_size_up << 16) | ptr->c_size_lo;
273     } else {
274         diag_printf1("start_bit=%d is not supported\n", start_bit);
275         while (1) {}
276     }
277     diag_printf1("start_bit=%d, end_bit=%d, value=0x%x\n", start_bit, end_bit, value);
278     return value;
279 }
280
281 static cyg_uint32 mmc_init(void)
282 {
283         cyg_uint32 status = FAIL;
284         command_t cmd;
285         response_t resp;
286
287         cyg_uint32 card_status = 0;
288
289
290         card_address = 0x1<<16;
291         /* get cid of MMC */
292         /* Configure CMD2 for card */
293         configure_cmd(&cmd,CMD2,NO_ARG,READ,RESPONSE_136,DISABLE,ONE);
294
295         /* Send CMD2 to card to determine CID contents */
296         if(send_cmd_and_wait_resp(&cmd) == FAIL)
297         {
298                 status = FAIL;
299                 return status;
300         }
301         else
302         {
303                  /* Read Command response  */
304                  read_response(RESPONSE_136, &resp);
305                  /* Assign CID values to mmc_cid structures */
306                 card_id.cid0 = resp.rsp0;
307                 card_id.cid1 = resp.rsp1;
308                 card_id.cid2 = resp.rsp2;
309                 card_id.cid3 = resp.rsp3;
310
311                 //status = PASS;
312         }
313
314         /* get rca of MMC */
315         /* Configure CMD3 for MMC card */
316         configure_cmd(&cmd,CMD3,card_address,READ,RESPONSE_48_CRC, DISABLE, ONE);
317
318         /* Assigns relative address to the card */
319         if(send_cmd_and_wait_resp(&cmd) == FAIL)
320         {
321                 status = FAIL;
322                 return status;
323         }
324         else
325         {
326                  /* Read Command response */
327                 read_response(RESPONSE_48_CRC, &resp);
328                 card_status = resp.rsp0;
329                 card_status = (((cyg_uint32) (card_status & CARD_STATE)) >> CARD_STATE_SHIFT);
330                 if(card_status == IDENT)
331                 {
332                         status = PASS;
333                 }
334                 else
335                 {
336                         status = FAIL;
337                         return status;
338                 }
339         }
340
341         card_get_csd();
342
343         configure_clk(trans_mode);
344
345         /*Send MMC to Transfer State */
346          /* Configure CMD7 for MMC card */
347         configure_cmd(&cmd,CMD7,card_address,READ,RESPONSE_48_CRC, DISABLE,ONE);
348
349         if(send_cmd_and_wait_resp(&cmd) == FAIL)
350         {
351                 status = FAIL;
352                 return status;
353         }
354         else
355         {
356                 /* Configure CMD13 to read status of the card becuase CMD7 has R1b response */
357                 configure_cmd(&cmd,CMD13,card_address,READ,RESPONSE_48_CRC,DISABLE,ONE);
358                 if(send_cmd_and_wait_resp(&cmd) == FAIL)
359                 {
360                         status = FAIL;
361                         return status;
362                 }
363                 else
364                 {
365                         /* Read Command response */
366                         read_response (RESPONSE_48_CRC, &resp);
367                         card_status = resp.rsp0;
368                         card_status = (((cyg_uint32) (card_status & CARD_STATE)) >> CARD_STATE_SHIFT);
369
370                         if(card_status == TRAN)
371                         {
372                                 status = PASS;
373                         }
374                         else
375                         {
376                                 status= FAIL;
377                         }
378                 }
379         }
380
381         return status;
382 }
383
384 static cyg_uint32 check_sd(void)
385 {
386         command_t cmd;
387         //command_response_t response;
388         cyg_uint32 count =0;
389         cyg_uint32 default_rca = 0;
390         cyg_uint32 ocr_value=0;
391         cyg_uint32 status = FAIL;
392         response_t resp;
393
394         configure_cmd(&cmd,CMD8,0x1AA,READ,RESPONSE_48_CRC, DISABLE, ONE);
395         send_cmd_and_wait_resp(&cmd);
396
397         while((count < 3000) && (status != PASS))
398         {
399                 /* Configure CMD55 for SD card */
400                 configure_cmd(&cmd,CMD55,default_rca,READ,RESPONSE_48_CRC, DISABLE, ONE);
401
402                 /* Send CMD55 to SD Memory card*/
403                 if(send_cmd_and_wait_resp(&cmd) == FAIL)
404                 {
405                         status = FAIL;
406                         //count++;
407                         diag_printf1("CMD55 FAIL!\n");
408                         break;
409                         //continue;
410                 }
411                 else
412                 {
413                         ocr_value = ((cyg_uint32)(OCR_VALUE) & 0xFFFFFFFF);
414                         /* Configure ACMD41 for SD card */
415                         configure_cmd(&cmd,ACMD41,ocr_value,READ,RESPONSE_48_WITHOUT_CRC,DISABLE, ONE);
416                         /* SEND ACMD41 to SD Memory card to determine OCR value */
417                         if(send_cmd_and_wait_resp(&cmd) == FAIL)
418                         {
419                                 status = FAIL;
420                                 diag_printf1("ACMD41 FAIL!\n");
421                                 break;
422                         }
423                         else
424                         {
425                                 /* Read Response from CMDRSP0 Register */
426                                 read_response(RESPONSE_48_WITHOUT_CRC, &resp);
427                                 ocr_value = resp.rsp0;
428                                  diag_printf1("SD: response ocr value: 0x%x\n", ocr_value);
429                                 /* Check if volatge lies in range or not*/
430                                 if((ocr_value & OCR_VALUE_MASK) == OCR_VALUE_MASK)
431                                 {
432                                         diag_printf1("response.cmd_rsp0: 0x%x\n", ocr_value);
433                                         /* Check if card busy bit is cleared or not */
434                                         if(ocr_value & CARD_BUSY)
435                                         {
436                                                 status = PASS;
437                                         }
438                                         else
439                                         {
440                                                 count++;
441                                                 diag_printf1("SD: Busy! \n");
442                                         }
443                                 }
444                                 else
445                                 {
446                                         count++;
447                                         diag_printf("SD: response ocr value: 0x%x  FAIL!\n", ocr_value);
448                                 }
449                         }
450                 }
451         }
452         return status;
453 }
454
455
456 static cyg_uint32 sd_init(cyg_uint32 bus_width)
457 {
458         cyg_uint32 status = FAIL;
459         command_t cmd;
460         response_t resp;
461         cyg_uint32 card_status = 0;
462         cyg_uint32 read_resp = 0;
463
464         card_address = 0;
465
466         /* get cid of MMC */
467         /* Configure CMD2 for card */
468         configure_cmd(&cmd,CMD2,NO_ARG,READ,RESPONSE_136,DISABLE,ONE);
469
470         /* Send CMD2 to card to determine CID contents */
471         if(send_cmd_and_wait_resp(&cmd) == FAIL)
472         {
473                 status = FAIL;
474                 return status;
475         }
476         else
477         {
478                  /* Read Command response  */
479                  read_response(RESPONSE_136, &resp);
480                  /* Assign CID values to mmc_cid structures */
481                 card_id.cid0 = resp.rsp0;
482                 card_id.cid1 = resp.rsp1;
483                 card_id.cid2 = resp.rsp2;
484                 card_id.cid3 = resp.rsp3;
485
486                 //status = PASS;
487         }
488
489         /* get rca of card */
490         /* Configure CMD3 for card */
491         configure_cmd(&cmd,CMD3,NO_ARG,READ,RESPONSE_48_CRC, DISABLE, ONE);
492
493         /* Assigns relative address to the card */
494         if(send_cmd_and_wait_resp(&cmd) == FAIL)
495         {
496                 status = FAIL;
497                 return status;
498         }
499         else
500         {
501                  /* Read Command response */
502                 read_response(RESPONSE_48_CRC, &resp);
503                  card_status = resp.rsp0;
504                  card_address = ((cyg_uint32) (card_status & (0xffffff00)));
505                 card_status = (((cyg_uint32) (card_status & CARD_STATE)) >> CARD_STATE_SHIFT);
506                 if(card_status == IDENT)
507                 {
508                         status = PASS;
509                 }
510                 else
511                 {
512                         status = FAIL;
513                         return status;
514                 }
515         }
516
517         card_get_csd();
518         configure_clk(trans_mode);
519
520         /*Send card to Transfer State */
521          /* Configure CMD7 for card */
522         configure_cmd(&cmd,CMD7,card_address,READ,RESPONSE_48_CRC, DISABLE,ONE);
523         if(send_cmd_and_wait_resp(&cmd) == FAIL)
524         {
525                 status = FAIL;
526                 return status;
527         }
528         else
529         {
530                 /* Configure CMD13 to read status of the card becuase CMD7 has R1b response */
531                 configure_cmd(&cmd,CMD13,card_address,READ,RESPONSE_48_CRC,
532                                     DISABLE,ONE);
533
534                 if(send_cmd_and_wait_resp(&cmd) == FAIL)
535                 {
536                         status = FAIL;
537                         return status;
538                 }
539                 else
540                 {
541                         /* Read Command response */
542                         read_response (RESPONSE_48_CRC, &resp);
543                         card_status = resp.rsp0;
544                         card_status = (((cyg_uint32) (card_status & CARD_STATE)) >> CARD_STATE_SHIFT);
545                         if(card_status == TRAN)
546                         {
547                                 status = PASS;
548                         }
549                         else
550                         {
551                                 status = FAIL;
552                         }
553                 }
554         }
555
556
557         /* set bus width */
558         if ((bus_width == FOUR ) || (bus_width == ONE))
559         {
560                 /* Configure CMD55 for SD card */
561                 configure_cmd(&cmd,CMD55,card_address,READ,RESPONSE_48_CRC, DISABLE, ONE);
562
563                 /* Issue CMD55 to SD Memory card*/
564                 if(send_cmd_and_wait_resp(&cmd) == FAIL)
565                 {
566                         status = FAIL;
567                         return status;
568                 }
569                 else
570                 {
571                         /* Read Command response */
572                         read_response(RESPONSE_48_CRC, &resp);
573                         read_resp = resp.rsp0;
574                         if(read_resp & SD_R1_APP_CMD_MSK)
575                         {
576                                 bus_width = (bus_width>>ONE);
577
578                                 /* Configure ACMD6 for SD card */
579                                 configure_cmd(&cmd,ACMD6,bus_width,READ,RESPONSE_48_CRC, DISABLE, ONE);
580                                 /* Send ACMD6 to SD Memory card*/
581                                 if(send_cmd_and_wait_resp(&cmd) == FAIL)
582                                 {
583                                         status = FAIL;
584                                         return status;
585                                 }
586                                 else
587                                 {
588                                         status = PASS;
589                                 }
590                         }
591                 }
592         }
593
594         return status;
595 }
596
597 static cyg_uint32 check_mmc(void)
598 {
599          command_t cmd;
600          response_t resp;
601         //cyg_uint32 response;
602         cyg_uint32 count=0;
603         cyg_uint32 ocr_value=0;
604         cyg_uint32 status = FAIL;
605
606
607         while((count < 10) && (status != PASS))
608         {
609         /* Configure CMD1 for MMC card */
610                 configure_cmd(&cmd, CMD1, OCR_VALUE, READ, RESPONSE_48_WITHOUT_CRC,DISABLE, ONE);
611
612                 /* Issue CMD1 to MMC card to determine OCR value */
613                 if(send_cmd_and_wait_resp(&cmd) == FAIL)
614                 {
615                         status = FAIL;
616                         count++;
617                         diag_printf1("CMD1 FAIL!\n");
618                         break;
619                         //continue;
620                 }
621                 else
622                 {
623                         read_response(RESPONSE_48_WITHOUT_CRC, &resp);
624                         ocr_value = resp.rsp0;
625
626                         /* Mask OCR value against 0x00FF8000 and compare with response*/
627                         if ((ocr_value & OCR_VALUE_MASK) == OCR_VALUE_MASK)
628                         {
629                                 /* Check if card busy bit is cleared or not */
630                                 if(ocr_value & CARD_BUSY)
631                                 {
632                                         status = PASS;
633                                 }
634                                 else
635                                 {
636                                         count++;
637                                 }
638                         }
639                         else
640                         {
641                                 count++;
642                         }
643                 }
644         }
645
646         return status;
647 }
648
649 static cyg_uint32 check_card(cyg_uint32 bus_width)
650 {
651
652         cyg_uint32 status = FAIL;
653         Card_Mode = NONE;
654
655         //wait
656     hal_delay_us(2000);
657         diag_printf1("check SD\n");
658         if(check_sd() == PASS){
659                 Card_Mode = SD;
660                 diag_printf1("SD init\n");
661                 status = sd_init(bus_width);
662                 Card_type  = ((csd.csd3 & CSD_STRUCT_MSK)? SD_CSD_2_0: SD_CSD_1_0);
663
664                 /* Card Command Class */
665                 CCC  = csd_get_value(&csd, 84, 95);
666         }
667         else{
668                 //wait
669         hal_delay_us(2000);
670                 diag_printf1("check MMC\n");
671                 if(check_mmc() == PASS){
672                         Card_Mode = MMC;
673
674                         status = mmc_init();
675                         Card_type = ((csd.csd3 & CSD_STRUCT_MSK) >> CSD_STRUCT_SHIFT) + SD_CSD_2_0;
676                 /* Card Command Class */
677                         CCC  = csd_get_value(&csd, 84, 95);
678                 }
679         }
680         return status;
681 }
682
683 static void sdhc_init(cyg_uint32 base_address)
684 {
685         cyg_uint32 iomux_base  = 0x43FAC000;
686         cyg_uint32 gpio_base  = 0x53FA4000;
687         cyg_uint32 iomux_sw_mux_ctl1 = readl(iomux_base + 0x18);
688         cyg_uint32 iomux_sw_mux_ctl2 = readl(iomux_base + 0x1C);
689         unsigned long reg;
690
691         iomux_sw_mux_ctl1 &= 0x000000FF;
692         iomux_sw_mux_ctl1 |=  0x12121200;
693         writel(iomux_sw_mux_ctl1, iomux_base + 0x18);
694
695         iomux_sw_mux_ctl2 &= 0xFF000000;
696         iomux_sw_mux_ctl2 |=  0x00121012;
697         writel(iomux_sw_mux_ctl2, iomux_base + 0x1C);
698
699         writel(0x0A529485, iomux_base + 0x168);
700         writel(0x0A5294A5, iomux_base + 0x16c);
701
702         /* Initialize base address */
703         pSDHC = (psdhc_t)base_address;
704 }
705
706 static void sdhc_reset(void)
707 {
708         pSDHC->sdhc_clk = SDHC_CLK_RESET;
709         pSDHC->sdhc_clk = SDHC_CLK_RESET | SDHC_CLK_STOP;
710         pSDHC->sdhc_clk = SDHC_CLK_STOP;
711         pSDHC->sdhc_clk = SDHC_CLK_STOP;
712         pSDHC->sdhc_clk = SDHC_CLK_STOP;
713         pSDHC->sdhc_clk = SDHC_CLK_STOP;
714         pSDHC->sdhc_clk = SDHC_CLK_STOP;
715         pSDHC->sdhc_clk = SDHC_CLK_STOP;
716         pSDHC->sdhc_clk = SDHC_CLK_STOP;
717         pSDHC->sdhc_clk = SDHC_CLK_STOP;
718 }
719
720 static cyg_uint32 card_reset(void)
721 {
722         command_t  cmd;
723
724         configure_clk(iden_mode);
725
726         /*set size of read and response fifo */
727         //pSDHC->sdhc_read_to = 0xffff;
728         pSDHC->sdhc_read_to = 0x2DB4;
729         pSDHC->sdhc_response_to = 0xff;
730         hal_delay_us(20000);
731
732         /* CMD0 to reset SD/MMC cards */
733         configure_cmd(&cmd,CMD0,NO_ARG,READ, RESPONSE_NO, DISABLE, ONE);
734
735         return send_cmd_and_wait_resp(&cmd);
736 }
737
738 static void wait_transfer_done(cyg_uint32 mask)
739 {
740         /* Wait interrupt (WRITE_OP_DONE/READ_OP_DONE) */
741         while(!(pSDHC->sdhc_status & mask));
742 }
743
744 static cyg_uint32 check_data(cyg_uint32 done_mask, cyg_uint32 crc_err_code_mask, cyg_uint32 crc_err_mask)
745 {
746         cyg_uint32 status = FAIL;
747         /* Check whether the interrupt is an OP_DONE or a data time out or a CRC error  */
748         if((pSDHC->sdhc_status & done_mask) &&
749             !(pSDHC->sdhc_status & crc_err_code_mask) &&
750             !(pSDHC->sdhc_status & crc_err_mask))
751         {
752                 status = PASS;
753         }
754         else
755         {
756                 status = FAIL;
757         }
758         return status;
759 }
760
761 static cyg_uint32 check_card_status(void)
762 {
763         command_t cmd;
764         cyg_uint32 status = PASS;
765         cyg_uint32 card_state;
766         cyg_uint32 read_resp;
767         response_t resp;
768         //cyg_uint32 card_address = (Card_rca << RCA_SHIFT);
769
770         configure_cmd(&cmd,CMD13,card_address,READ,RESPONSE_48_CRC, DISABLE, ONE);
771
772         if(send_cmd_and_wait_resp(&cmd) == FAIL)
773         {
774                 status = FAIL;
775         }
776         else
777         {
778                 /* Read Command response */
779                 read_response (RESPONSE_48_CRC, &resp);
780                 read_resp = resp.rsp0;
781                 card_state = ((cyg_uint32) (read_resp & CARD_STATE) >> CARD_STATE_SHIFT);
782
783                 if(card_state == TRAN)
784                 {
785                         status = PASS;
786                 }
787                 else
788                 {
789                         status = FAIL;
790                 }
791         }
792         return status;
793 }
794
795
796
797 /*==========================================================================
798 FUNCTION: static cyg_uint32 card_get_capacity_size(void)
799 DESCRIPTION:
800    this function will analize MMC/SD CSD register and return the capacity size (in unit of KB)
801
802 ARGUMENTS PASSED:
803    None
804
805 RETURN VALUE:
806    cyg_uint32
807
808 PRE-CONDITIONS:
809    None
810
811 POST-CONDITIONS:
812    None
813
814 Detailed Description:
815 ==============================================================================*/
816 cyg_uint32 card_get_capacity_size (void)
817 {
818         cyg_uint32 capacity = 0;
819         cyg_uint32 c_size, c_size_mult, blk_len;
820
821         if(!csd.csd0  && !csd.csd1  && !csd.csd2 && !csd.csd3)
822                 diag_printf("WARNINGS:card_init should be done first!\n");
823
824         switch(Card_type)
825         {
826                 case SD_CSD_1_0:
827                 case MMC_CSD_1_0:
828                 case MMC_CSD_1_1:
829                 case MMC_CSD_1_2:
830                 case SD_CSD_2_0:
831                         c_size = csd_get_value(&csd, 62, 73);
832                         c_size_mult = csd_get_value(&csd, 47, 49);
833                         blk_len = csd_get_value(&csd, 80, 83);
834                         capacity = (((c_size+1) << (c_size_mult +2)) << blk_len) / 1024;
835                         diag_printf1("c_size=0x%x, c_size_mult=0x%x, blk_len=0x%x, capacity(KB)=0x%x\n",
836                                                   c_size, c_size_mult, blk_len, capacity);
837                         break;
838 #if 0 // todo
839                 case SD_CSD_2_0:
840                         //blk_len = csd_get_value(&csd, 80, 83);
841                         c_size = csd_get_value(&csd, 48, 69);
842                         capacity = (c_size + 1) * 512; // block length is fixed to 512B
843             diag_printf1("card capacity2=0x%x\n", capacity);
844                         break;
845 #endif
846                 default:
847                         break;
848         }
849         if (capacity > (0x80000000 / 1024))
850                 HighCapacityCard = 1;
851         else
852                 HighCapacityCard = 0;
853
854         return capacity;
855 }
856
857 cyg_uint32 mxcmci_init (cyg_uint32 bus_width, cyg_uint32 base_address)
858 {
859         sdhc_init(base_address);
860
861         /* Software Reset to SDHC */
862         sdhc_reset();
863
864         /* Software Reset to card */
865         card_reset();
866
867         return check_card(bus_width);
868 }
869
870 cyg_uint32 mmc_data_read (cyg_uint32 *ram_ptr, cyg_uint32 length, cyg_uint32 offset)
871 {
872         command_t cmd;
873         cyg_uint32 len, retry = 15;
874         cyg_uint32 status = PASS;
875         cyg_uint32 i, j, k = 0;
876
877         diag_printf1("\ncard_data_read !-- offset: %x, length: %x \n", offset, length);
878
879         len = (length + BLOCK_LEN - 1) & (~(BLOCK_LEN - 1));
880
881         if (HighCapacityCard)
882                 offset = offset / 512;
883
884         /* Configure SDHC block and number of blocks */
885         pSDHC->sdhc_blk_len = BLOCK_LEN;
886         pSDHC->sdhc_nob = 0x1;
887
888         /* Configure CMD16 to set block length as 512 bytes.*/
889         configure_cmd(&cmd,CMD16,BLOCK_LEN,READ,RESPONSE_48_CRC, DISABLE, ONE);
890         if(send_cmd_and_wait_resp(&cmd) == FAIL)
891         {
892                 status = FAIL;
893                 diag_printf1("CMD16 Fail!\n");
894         }
895         else
896         {
897                 while(len != 0 && !status)
898                 {
899                         //check card status whether it is in transfer mode, so as to start next transfer
900                         while((status = check_card_status())!=PASS);
901
902                         diag_printf1("length left: %x \n", len);
903
904                         /* Send CMD17 for single block read */
905                         configure_cmd(&cmd,CMD17,offset,READ,RESPONSE_48_CRC, ENABLE, ONE);
906                         if(send_cmd_and_wait_resp(&cmd) == FAIL)
907                         {
908                                 status= FAIL;
909                                 diag_printf1("CMD17 Fail!\n");
910                         }
911                         else
912                         {
913                                  /* Enable int */
914                                 pSDHC->sdhc_int_cntr = SDHC_INT;
915                                 for(i = 0; i < BLOCK_LEN/16; i++)
916                                 {
917                                         /* Wait for BRR bit to be set */
918                                         while(!(pSDHC->sdhc_status & SDHC_STATUS_BUF_READ_RDY_MSK)) {
919                                                 hal_delay_us(10);
920                                         }
921                                         for(j=0;j<4;j++)
922                                         {
923                                                 /* Read 32 bit data from buffer access fifo */
924                                                 *ram_ptr = pSDHC->sdhc_buffer_access;
925                                                 ram_ptr++;
926                                         }
927                                 }
928                                 /* Wait for transfer complete  */
929                                 wait_transfer_done(SDHC_STATUS_READ_OP_DONE_MSK);
930
931                                 /* Check for status errors (crc or timeout)*/
932                                 status = check_data(SDHC_STATUS_READ_OP_DONE_MSK, SDHC_STATUS_TIME_OUT_READ, SDHC_STATUS_READ_CRC_ERR_MSK);
933
934                                 offset = offset + BLOCK_LEN;
935                                 len = len - BLOCK_LEN;
936                                 //ram_ptr= ram_ptr + (BLOCK_LEN/4);
937                                 diag_printf1("length left3: %x \n", len);
938                         }
939                 }
940         }
941         diag_printf1("End of card data read!\n");
942         return status;
943 }
944
945 cyg_uint32 mmc_data_write (cyg_uint32 *ram_ptr, cyg_uint32 length, cyg_uint32 offset)
946 {
947         command_t cmd;
948         cyg_uint32 len;
949         cyg_uint32 status = PASS;
950         cyg_uint32 i, j = 0;
951
952         len = (length + BLOCK_LEN - 1) & (~(BLOCK_LEN - 1));
953
954         /* Configure SDHC block and number of blocks */
955         pSDHC->sdhc_blk_len = BLOCK_LEN;
956         pSDHC->sdhc_nob = 0x1;
957
958     /* high capacity card uses sector mode */
959         if (HighCapacityCard)
960                 offset = offset / 512;
961
962         /* Send CMD16 to set block length as 512 bytes.*/
963         configure_cmd(&cmd,CMD16,BLOCK_LEN,READ,RESPONSE_48_CRC, DISABLE, ONE);
964         if(send_cmd_and_wait_resp(&cmd) == FAIL)
965         {
966                 status = FAIL;
967         }
968         else
969         {
970                 while(len != 0 && !status)
971                 {
972                         //check card status whether it is in transfer mode, so as to start next transfer
973                         while((status = check_card_status())!=PASS);
974                         /* Comfigure command CMD24 for block write--write address */
975                         configure_cmd(&cmd,CMD24,offset,WRITE,RESPONSE_48_CRC, ENABLE, ONE);
976                         if(send_cmd_and_wait_resp(&cmd) == FAIL)
977                         {
978                                 status = FAIL;
979                         }
980                         else
981                         {
982                                  /* Enable int */
983                                 pSDHC->sdhc_int_cntr = SDHC_INT;
984
985                                 for(i = 0; i < (BLOCK_LEN)/4; i++)
986                                 {
987                                         /* Wait for BWR bit to be set */
988                                         while(!(pSDHC->sdhc_status & SDHC_STATUS_BUF_WRITE_RDY_MSK));
989                                         //copy data from ram to sdhc buffer access fifo
990                                         pSDHC->sdhc_buffer_access = *ram_ptr;
991                                         ram_ptr++;
992                                 }
993
994                                 /* Wait for transfer done */
995                                 wait_transfer_done(SDHC_STATUS_WRITE_OP_DONE_MSK);
996
997                                 /* Check for status errors (crc or timeout)*/
998                                 status = check_data(SDHC_STATUS_WRITE_OP_DONE_MSK, 0, SDHC_STATUS_WRITE_CRC_ERR_MSK);
999
1000                                 len = len - BLOCK_LEN;
1001                                 offset +=  BLOCK_LEN;
1002                                 //ram_ptr = ram_ptr + (BLOCK_LEN/4);
1003                         }
1004                 }
1005         }
1006         return status;
1007 }
1008
1009 cyg_uint32 mmc_data_erase (cyg_uint32 offset, cyg_uint32 size)
1010 {
1011         command_t cmd;
1012         cyg_uint32 startEraseBlockCmd;
1013         cyg_uint32 endEraseBlockCmd;
1014         cyg_uint32 startBlock = offset/BLOCK_LEN;
1015         cyg_uint32 endBlock = (offset+size)/BLOCK_LEN;
1016         cyg_uint32 status = FAIL;
1017
1018         /* Fix erase operation on MX31/32 */
1019         return 0;
1020         if(Card_Mode == MMC) {
1021                 startBlock *=BLOCK_LEN;
1022                 endBlock *= BLOCK_LEN;
1023                 startEraseBlockCmd = CMD35;
1024                 endEraseBlockCmd   = CMD36;
1025         }
1026         else if(Card_Mode == SD) {
1027                 startBlock *=BLOCK_LEN;
1028                 endBlock *= BLOCK_LEN;
1029                 startEraseBlockCmd = CMD32;
1030                 endEraseBlockCmd   = CMD33;
1031         }
1032         if (HighCapacityCard) {
1033                 startBlock /= BLOCK_LEN;
1034                 endBlock /= BLOCK_LEN;
1035         }
1036
1037         /* Configure start erase command to set first block*/
1038         configure_cmd(&cmd,startEraseBlockCmd,startBlock,READ,RESPONSE_48_CRC, DISABLE, ONE);
1039         if((status = send_cmd_and_wait_resp(&cmd)) == PASS){
1040
1041                 /* Configure end erase command to set end block*/
1042                 configure_cmd(&cmd,endEraseBlockCmd,endBlock,READ,RESPONSE_48_CRC, DISABLE, ONE);
1043                 if((status = send_cmd_and_wait_resp(&cmd)) == PASS){
1044                         /* Comfigure command to start erase*/
1045                         configure_cmd(&cmd,CMD38,0,READ,RESPONSE_48_CRC, DISABLE, ONE);
1046                         if((status = send_cmd_and_wait_resp(&cmd)) == PASS){
1047                                 //wait for completion
1048                                 return status;
1049                         }
1050                 }
1051         }
1052
1053         return status;
1054 }
1055
1056 cyg_uint32 card_flash_query(void* data)
1057 {
1058         command_t cmd;
1059         cyg_uint32 status = PASS;
1060         response_t response;
1061
1062          // Configure CMD2 for card  No Argument is expected for CMD2
1063         configure_cmd(&cmd,CMD2,NO_ARG,READ,RESPONSE_136, DISABLE, ONE);
1064
1065         // Send CMD2 to card to determine CID contents
1066         if(send_cmd_and_wait_resp(&cmd) == FAIL)
1067         {
1068         status = FAIL;
1069                 diag_printf("%s: can't send query command\n", __FUNCTION__);
1070         }
1071         else
1072         {
1073                 cyg_uint32* d = (cyg_uint32*)data;
1074                 // Read Command response
1075                 read_response (RESPONSE_136, &response);
1076
1077                 // Assign CID values to mmc_cid structures
1078                 *d++ = response.rsp0;
1079                 *d++ = response.rsp1;
1080                 *d++= response.rsp2;
1081                 *d= response.rsp3;
1082
1083                 // Assign cid_request as SUCCESS
1084                 status = PASS;
1085         }
1086         diag_printf( "%s(PASS?=%d):(ID=0x%x: 0x%x, 0x%x, 0x%x)\n",
1087         __FUNCTION__, status,*(cyg_uint32*)(data), *(cyg_uint32*)((cyg_uint32)data+4),
1088                *(cyg_uint8*)((cyg_uint32)data+8), *(cyg_uint8*)((cyg_uint32)data+12));
1089         return;
1090 }
1091
1092