source: umon/ports/beagleboneblack/omap3530_sdmmc.c @ dee5246

Last change on this file since dee5246 was dee5246, checked in by Jarielle Catbagan <jcatbagan93@…>, on 06/19/15 at 18:53:54

Duplicated csb740 directory to beagleboneblack directory for BBB port

  • Property mode set to 100644
File size: 12.1 KB
Line 
1/* NOTE:
2 * THIS CODE IS NOT READY FOR USE YET!!!
3 */
4#include "config.h"
5#include "cpuio.h"
6#include "genlib.h"
7#include "stddefs.h"
8#include "timer.h"
9#include "omap3530.h"
10#include "sd.h"
11
12
13#define MMCTMOUT        2000
14
15/* This code is included here just for simulating the SD
16 * interface (temporarily if a real one isn't ready.  In a real system,
17 * the INCLUDE_SD_DUMMY_FUNCS definition would be off.
18 */
19int
20xsdCmd(unsigned long cmd, unsigned short argh, unsigned short argl)
21{
22        vulong  stat, rsp;
23        struct elapsed_tmr tmr;
24
25        printf("sdCmd(0x%08lx) (cmd=%d)\n",cmd,(cmd & 0x3f000000) >> 24);
26
27        startElapsedTimer(&tmr,MMCTMOUT);               // Wait for command line not-in-use
28        while(MMC1_REG(MMCHS_PSTATE) & CMDI) {
29                if(msecElapsed(&tmr)) {
30            printf("sdInit: CMDI timeout\n");
31            return(-1);
32        }
33        }
34
35        MMC1_REG(MMCHS_ARG) = ((argh << 16) | argl);
36        MMC1_REG(MMCHS_IE) = 0xfffffeff;
37        MMC1_REG(MMCHS_CMD) = cmd;
38
39again:
40        stat = MMC1_REG(MMCHS_STAT);
41        if (stat & CTO) {
42                if (stat & CCRC)
43                        printf("cmdline in use\n");
44                else
45                        printf("CTO1 CCRC0\n");
46                MMC1_REG(MMCHS_SYSCTL) |= SRC;
47                startElapsedTimer(&tmr,MMCTMOUT);       
48                while(MMC1_REG(MMCHS_SYSCTL) & SRC) {
49                        if(msecElapsed(&tmr))
50                                printf("sdInit: SRC timeout\n");
51                }
52                return(-1);
53        }
54        if ((stat & CC)  == 0)
55                goto again;
56               
57        cmd = MMC1_REG(MMCHS_CMD);
58        if ((cmd & RSPTYPE) == RSPTYPE_NONE) {
59                printf("Success!\n");   
60                return(0);
61        }
62
63        if ((cmd & RSPTYPE) == RSPTYPE_136) {
64                rsp = MMC1_REG(MMCHS_RSP10);
65                printf("RSP0: %04x, RSP1: %04x\n",
66                        rsp & 0xffff,(rsp & 0xffff0000) >> 16);
67                rsp = MMC1_REG(MMCHS_RSP32);
68                printf("RSP2: %04x, RSP3: %04x\n",
69                        rsp & 0xffff,(rsp & 0xffff0000) >> 16);
70                rsp = MMC1_REG(MMCHS_RSP54);
71                printf("RSP4: %04x, RSP5: %04x\n",
72                        rsp & 0xffff,(rsp & 0xffff0000) >> 16);
73                rsp = MMC1_REG(MMCHS_RSP76);
74                printf("RSP6: %04x, RSP7: %04x\n",
75                        rsp & 0xffff,(rsp & 0xffff0000) >> 16);
76        }
77        if ((cmd & RSPTYPE) == RSPTYPE_48) {
78                rsp = MMC1_REG(MMCHS_RSP10);
79                printf("RSP0: %04x, RSP1: %04x\n",
80                        rsp & 0xffff,(rsp & 0xffff0000) >> 16);
81                rsp = MMC1_REG(MMCHS_RSP32);
82                printf("RSP2: %04x, RSP3: %04x\n",
83                        rsp & 0xffff,(rsp & 0xffff0000) >> 16);
84        }
85        if ((cmd & RSPTYPE) == RSPTYPE_48BSY) {
86                rsp = MMC1_REG(MMCHS_RSP10);
87                printf("RSP0: %04x, RSP1: %04x\n",
88                        rsp & 0xffff,(rsp & 0xffff0000) >> 16);
89                rsp = MMC1_REG(MMCHS_RSP32);
90                printf("RSP2: %04x, RSP3: %04x\n",
91                        rsp & 0xffff,(rsp & 0xffff0000) >> 16);
92        }
93
94        return(0);
95}
96
97int
98sdCmd(unsigned long cmd, unsigned short argh, unsigned short argl)
99{
100        vulong  stat, arg;
101        struct elapsed_tmr tmr;
102
103        printf("sdCmd(0x%08lx) (cmd=%d)\n",cmd,(cmd & 0x3f000000) >> 24);
104
105        MMC1_REG(MMCHS_STAT) = 0xffffffff;
106        MMC1_REG(MMCHS_BLK) =  NBLK(1) | BLEN(512);
107        MMC1_REG(MMCHS_SYSCTL) &=  ~DTOMSK;
108        MMC1_REG(MMCHS_SYSCTL) |= DTO(14);
109
110        startElapsedTimer(&tmr,MMCTMOUT);               // Wait for command line not-in-use
111        while(MMC1_REG(MMCHS_PSTATE) & CMDI) {
112                if(msecElapsed(&tmr)) {
113            printf("sdCmd: CMDI timeout\n");
114            return(-1);
115        }
116                monDelay(1);
117        }
118
119        arg = argh;
120        arg <<= 16;
121        arg |= argl;
122        MMC1_REG(MMCHS_ARG) = arg;
123        MMC1_REG(MMCHS_IE) = 0xfffffeff;
124        MMC1_REG(MMCHS_CMD) = cmd;
125
126        startElapsedTimer(&tmr,MMCTMOUT);
127        do {
128                stat = MMC1_REG(MMCHS_STAT);
129                if (stat & CTO) {
130                        if (stat & CCRC)
131                                printf("CCRC1\n");
132                        else
133                                printf("CTO1 CCRC0\n");
134                        MMC1_REG(MMCHS_SYSCTL) |= SRC;
135                        startElapsedTimer(&tmr,MMCTMOUT);       
136                        while(MMC1_REG(MMCHS_SYSCTL) & SRC) {
137                                if(msecElapsed(&tmr))
138                                        printf("sdCmd: SRC timeout\n");
139                        }
140                        return(-1);
141                }
142                if(msecElapsed(&tmr)) {
143            printf("sdCmd: CC timeout\n");
144            return(-1);
145        }
146                monDelay(1);
147        } while ((stat & CC) == 0);
148
149        stat = MMC1_REG(MMCHS_STAT);
150        if (stat & CCRC)
151                printf("Cmd crc\n");
152        if (stat & DCRC)
153                printf("Data crc\n");
154        if (stat & CERR)  {
155                printf("Card error 0x%lx\n",stat);
156                return(-1);
157        }
158        if (stat & CTO) {
159                printf("CTO set!\n");
160                return(-1);
161        }
162        if (stat & CC) {
163                printf("Success!\n");   
164                return(0);
165        }
166        else {
167                printf("Didn't complete!\n");   
168                return(-1);
169        }
170}
171
172int
173sdClkSet(int clkval)
174{
175        vulong reg;
176        struct elapsed_tmr tmr;
177
178        MMC1_REG(MMCHS_SYSCTL) &= ~CEN;
179        reg = MMC1_REG(MMCHS_SYSCTL);
180        reg &= ~CLKDMSK;
181        reg |= CLKD(96000/clkval);
182        MMC1_REG(MMCHS_SYSCTL) = reg;
183
184        startElapsedTimer(&tmr,MMCTMOUT);                       // Wait for clock stable
185        while((MMC1_REG(MMCHS_SYSCTL) & ICS) == 0) {
186                if(msecElapsed(&tmr)) {
187                        printf("sdClkSet: ICS timeout\n");
188                        return(-1);
189                }
190                monDelay(1);
191        }
192        MMC1_REG(MMCHS_SYSCTL) |= CEN;
193        startElapsedTimer(&tmr,MMCTMOUT);                       // Wait for clock stable
194        while((MMC1_REG(MMCHS_SYSCTL) & CEN) == 0) {
195                if(msecElapsed(&tmr)) {
196            printf("sdClkSet: ICS timeout\n");
197            return(-1);
198        }
199                monDelay(1);
200        }
201        return(0);
202}
203
204/* sdInit():
205 * This function is called by the "sd init" command on the command line.
206 * Where applicable, the text refers to the section in the Sept 2008
207 * Technical Reference Manual (TRM) from which I got the code/functionality.
208 */
209int
210sdInit(int interface, int verbose)
211{
212        int i, pbiasretry = 0;
213        vulong reg;
214        struct elapsed_tmr tmr;
215
216        /* There's only one interface on the CSB740, so reject anything
217         * other than interface 0...
218         */
219        if (interface != 0)
220                return(-1);
221
222        /*******************************
223         *
224         * Clock configuration:
225         * (TRM 22.5.1.1)
226         */
227        *(vulong *)CM_ICLKEN1_CORE |= EN_MMC1;  // Configure interface and
228        *(vulong *)CM_FCLKEN1_CORE |= EN_MMC1;  // functional clocks.
229
230        /*******************************
231         *
232         * Not really sure what this is... apparently some kind of clock steering.
233         * I tried both setting the bit and clearing it.  Made no difference.
234         * In both cases the clock was present on the CLK pin.
235         */
236        *(vulong *)CONTROL_DEVCONF0 |= MMCSDIO1ADPCLKISEL;
237
238        /********************************
239         *
240         * Set up BIAS (this allows the pins to run at 1.8 or 3.0 volts I think).
241         * This is configured as 0606 in rom_reset.S (i don't think thats right).
242         * Note: The CSB703 ties this interface to 3.3 volts.
243         * TRM 22.5.3
244         * TRM 7.5.2 and flowchart in figure 7-24...
245         */
246pbias_retry:
247        *(vulong *)CONTROL_PBIAS_LITE = PBIAS_LITE_VMMC1_52MHZ;
248        monDelay(100);
249        *(vulong *)CONTROL_PBIAS_LITE |= MMC_PWR_STABLE;
250        monDelay(100);
251        if (*(vulong *)CONTROL_PBIAS_LITE & PBIAS_LITE_MMC1_ERROR) {
252                *(vulong *)CONTROL_PBIAS_LITE &= (~MMC_PWR_STABLE);
253                monDelay(100);
254                if (pbiasretry++ < 3) {
255                        goto pbias_retry;
256                }
257                else {
258            printf("sdInit: PBIAS timeout\n");
259            return(-1);
260                }
261        }
262
263#if 0
264        /*******************************
265         *
266         * These registers are things I found when scouring the TRM for "MMC".
267         * I don't think they have any affect on basic startup of the interface
268         * so they are removed for now...
269         */
270        *(vulong *)CM_AUTOIDLE1_CORE &= ~AUTO_MMC1;             // Disable auto clock enable
271        *(vulong *)PM_WKEN1_CORE &= ~EN_MMC1;                   // Disable wakeup event
272        *(vulong *)PM_MPUGRPSEL1_CORE &= ~GRPSEL_MMC1;  // Disable mpu-group wakeup
273        *(vulong *)PM_IVA2GRPSEL1_CORE &= ~GRPSEL_MMC1; // Disable iva2-group wakeup
274        *(vulong *)PM_WKST1_CORE &= ~EN_MMC1;                   // Clear wakeup status
275#endif
276
277        /*******************************
278         *
279         * Issue soft reset and wait for completion...
280         * (TRM 22.5.1.2)
281         */
282        MMC1_REG(MMCHS_SYSCONFIG) |= SRESET;                    // Software reset
283        if ((MMC1_REG(MMCHS_SYSSTATUS) & RESETDONE) == 0)
284                printf("Good, RESETDONE is low here\n");
285
286        startElapsedTimer(&tmr,MMCTMOUT);                                       // Wait for completion
287        while((MMC1_REG(MMCHS_SYSSTATUS) & RESETDONE) == 0) {
288                if(msecElapsed(&tmr)) {
289            printf("sdInit: SRST failed\n");
290            return(-1);
291        }
292        }
293        /********************************
294         *
295         * Set SRA bit, then wait for it to clear.
296         */
297        MMC1_REG(MMCHS_SYSCTL) |= SRA;
298        startElapsedTimer(&tmr,MMCTMOUT);
299        while((MMC1_REG(MMCHS_SYSCTL) & SRA)) {
300                if(msecElapsed(&tmr)) {
301            printf("sdInit: SRA timeout\n");
302            return(-1);
303        }
304        }
305       
306        startElapsedTimer(&tmr,MMCTMOUT);               // Wait for debounce stable.
307        while((MMC1_REG(MMCHS_PSTATE) & DEBOUNCE) != DEBOUNCE) {
308                if(msecElapsed(&tmr)) {
309            printf("sdInit: DEBOUNCE timeout\n");
310            return(-1);
311        }
312        }
313
314        /*******************************
315         *
316         * Establish hardware capabilities:
317         * TRM 22.5.1.3
318         */
319        reg = MMC1_REG(MMCHS_CAPA);
320        reg &= ~(VS18 | VS30 | VS33);
321        reg |= VS18;
322        MMC1_REG(MMCHS_CAPA) = reg;
323
324#if 0
325        /********************************
326         *
327         * Enable wakeup mode (don't think I need this, tried both ways)
328         * TRM 22.5.1.4
329         */
330        MMC1_REG(MMCHS_SYSCONFIG) |= ENWAKEUP;
331        MMC1_REG(MMCHS_HCTL) |= IWE;
332#endif
333       
334        /********************************
335         *
336         * MMC Host and Bus Configuration
337         * TRM 22.5.1.5
338         */
339        //MMC1_REG(MMCHS_CON) =
340        MMC1_REG(MMCHS_HCTL) &= ~SVDS;
341        MMC1_REG(MMCHS_HCTL) |= SVDS18;
342        monDelay(10);
343        MMC1_REG(MMCHS_HCTL) |= SDBP;
344        monDelay(100);
345       
346        startElapsedTimer(&tmr,MMCTMOUT);                       // Wait for SVDS verification
347        while((MMC1_REG(MMCHS_HCTL) & SDBP) == 0) {
348                if(msecElapsed(&tmr)) {
349            printf("sdInit: SDBP timeout\n");
350            return(-1);
351        }
352        }
353
354        MMC1_REG(MMCHS_SYSCTL) |= ICE;                  // Enable internal clock
355
356        MMC1_REG(MMCHS_SYSCTL) &= ~CLKDMSK;             // Set clock divisor:
357        MMC1_REG(MMCHS_SYSCTL) |= CLKD(960);    // (should be <= 80Khz initially)
358
359        startElapsedTimer(&tmr,MMCTMOUT);                       // Wait for clock stable
360        while((MMC1_REG(MMCHS_SYSCTL) & ICS) == 0) {
361                if(msecElapsed(&tmr)) {
362            printf("sdInit: ICS timeout\n");
363            return(-1);
364        }
365        }
366
367        /* I set these two bits with the hope that the clock will be
368         * active even if there is no card installed (so I atleast can
369         * see *some* activity).
370         */
371        MMC1_REG(MMCHS_SYSCTL) |= CEN;                  // External clock enable
372#if 0
373        MMC1_REG(MMCHS_CON) |= CLKEXTFREE;
374
375        reg = MMC1_REG(MMCHS_SYSCONFIG);
376        reg &= ~SIDLEMODEMSK;
377        reg &= ~CLKACTIVITYMSK;
378        reg &= ~AUTOIDLE;
379        reg |= (SIDLEMODE(1) | CLKACTIVITY(3));
380        MMC1_REG(MMCHS_SYSCONFIG) = reg;
381#endif
382
383        /********************************
384         *
385         * Set the INIT bit to send an initialization stream to the card...
386         * (top of left flowchart in TRM section 22.5.2.1)
387         */
388        MMC1_REG(MMCHS_CON) |= MMCINIT;
389        for(i=0;i<10;i++) {
390                sdCmd(CMD(0) | RSPTYPE_NONE,0,0);
391                monDelay(2);
392        }
393        MMC1_REG(MMCHS_CON) &= ~MMCINIT;
394        MMC1_REG(MMCHS_STAT) = 0xffffffff;
395
396        if (sdClkSet(400) != 0)
397                return(-1);
398
399        /* this is the get_card_type() function in the code from TI...
400         */
401        if (sdCmd(CMD(55) | RSPTYPE_48,0,0) < 0) {
402                printf("Card type = MMC\n");
403                MMC1_REG(MMCHS_CON) |= ODE;
404        }
405        else {
406                if ((MMC1_REG(MMCHS_RSP10) & 0xffff) == 0x0120) {
407                        printf("Card type = SD\n");
408                }
409                else {
410                        printf("Card type = MMC_CARD\n");
411                        MMC1_REG(MMCHS_CON) |= ODE;
412                }
413        }
414
415       
416#if 0
417        /********************************
418         *
419         * Send Command 5
420         * (top of right flowchart in TRM section 22.5.2.1)
421         */
422        sdCmd(CMD(5) | RSPTYPE_NONE,0,0);
423
424        startElapsedTimer(&tmr,MMCTMOUT);
425        do {
426                reg = MMC1_REG(MMCHS_STAT);
427                if (reg & CC) {
428                        /* For now we assume only SD cards... */
429                        printf("SDIO detected!!!  Shouldn't be here!\n");
430                        return(-1);
431                }
432                if(msecElapsed(&tmr)) {
433            printf("sdInit: CTO timeout1\n");
434            return(-1);
435        }
436               
437        } while((reg & CTO) == 0);
438
439        /********************************
440         *
441         * Set SRC bit, then wait for it to clear.
442         * (midway down right flowchart in TRM section 22.5.2.1)
443         */
444        MMC1_REG(MMCHS_SYSCTL) |= SRC;
445        startElapsedTimer(&tmr,MMCTMOUT);
446        while((MMC1_REG(MMCHS_SYSCTL) & SRC)) {
447                if(msecElapsed(&tmr)) {
448            printf("sdInit: SRC timeout\n");
449            return(-1);
450        }
451        }
452
453        sdCmd(CMD(8) | RSPTYPE_NONE,0,0);
454
455        startElapsedTimer(&tmr,MMCTMOUT);
456        do {
457                reg = MMC1_REG(MMCHS_STAT);
458                if (reg & CC) {
459                        /* For now we assume only SD cards... */
460                        printf("SD BINGO!!!  This is where we want to be!\n");
461                        return(0);
462                }
463                if(msecElapsed(&tmr)) {
464            printf("sdInit: CTO timeout2\n");
465            return(-1);
466        }
467               
468        } while((reg & CTO) == 0);
469
470        /* For now we assume only SD cards... */
471        printf("MMC detected!!!  Shouldn't be here!\n");
472#endif
473        return(-1);
474}
475
476int
477sdRead(int interface, char *buf, int blk, int blkcnt)
478{
479        char *from;
480        int     size;
481
482        if (interface != 0)
483                return(-1);
484
485        from = (char *)(blk * SD_BLKSIZE);
486        size = blkcnt * SD_BLKSIZE;
487        memcpy(buf,from,size);
488        return(0);
489}
490
491int
492sdWrite(int interface, char *buf, int blk, int blkcnt)
493{
494        char *to;
495        int     size;
496
497        if (interface != 0)
498                return(-1);
499
500        to = (char *)(blk * SD_BLKSIZE);
501        size = blkcnt * SD_BLKSIZE;
502        memcpy(to,buf,size);
503        return(0);
504}
505
Note: See TracBrowser for help on using the repository browser.