]> git.ozlabs.org Git - minimigmac.git/blob - pic/mmc.c
Initial commit
[minimigmac.git] / pic / mmc.c
1 /*
2  * MMC/SD-Card driver
3  *
4  * Essentially copied from Minimig
5  *
6  * Current implementation is polled & synchronous
7  */
8
9 #include <stdio.h>
10
11 #include "hardware.h"
12 #include "mmc.h"
13 #include "mmc_cmds.h"
14
15 /* Enable / Disable Debug info */
16 #undef DEBUG_SDMMC
17
18 /* MMC, or SD Card Specifification V1, V2, SDHC */
19 #define MMC_CARD_NONE                   0x00
20 #define MMC_CARD_MMC                    0x01
21 #define MMC_CARD_SD_RAW_SPEC_1          0x02
22 #define MMC_CARD_SD_RAW_SPEC_2          0x04
23 #define MMC_CARD_SD_RAW_SPEC_SDHC       0x08
24
25 static unsigned char mmc_card;
26 static unsigned char mmc_crc_7;
27 static unsigned int mmc_timeout;
28 static unsigned char mmc_resp[5];
29
30 #ifdef DEBUG_SDMMC
31 #define pr_debug(args...)       printf_tiny(args)
32 #else
33 #define pr_debug(args...)
34 #endif
35
36 /* Calculate CRC7 checksum */
37 static void mmc_add_crc7(unsigned char c)
38 {
39         unsigned char i;
40
41         for (i = 0; i < 8; i++) {
42                 mmc_crc_7 <<= 1;
43                 if (c & 0x80)
44                         mmc_crc_7 ^= 0x09;
45                 if (mmc_crc_7 & 0x80)
46                         mmc_crc_7 ^= 0x09;
47                 c <<= 1;
48         }
49 }
50
51 /* Send a byte and calculate CRC */
52 static void mmc_spi_crc(unsigned char cmd)
53 {
54         do_spi(cmd);
55         mmc_add_crc7(cmd);
56 }
57
58 /* Send a command to the SDcard */
59 static void mmc_cmd_r0(char cmd, unsigned short addr_h, unsigned short addr_l)
60 {
61         mmc_crc_7 = 0;
62
63         /* Flush SPI-bus */
64         do_spi(0xff);
65
66         /* Send command */
67         mmc_spi_crc(cmd);
68
69         /* Send address */
70         mmc_spi_crc(addr_h >> 8);
71         mmc_spi_crc(addr_h & 0xff);
72         mmc_spi_crc(addr_l >> 8);
73         mmc_spi_crc(addr_l & 0xff);
74
75         /* Cook and send CRC */
76         mmc_crc_7 <<= 1;
77         mmc_crc_7++;
78         do_spi(mmc_crc_7);
79 }
80
81 /* Send a command to the SDcard, a one byte response is expected */
82 static void mmc_cmd_r1(char cmd, unsigned short addr_h, unsigned short addr_l)
83 {
84         unsigned char i = 100;
85
86         mmc_cmd_r0(cmd, addr_h, addr_l);
87         do
88                 mmc_resp[0] = do_spi(0xff);
89         while (mmc_resp[0] == 0xff && --i);
90 }
91
92 /* Send a command to the SDcard, a two byte response is expected */
93 static void mmc_cmd_r2(char cmd, unsigned short addr_h, unsigned short addr_l)
94 {
95         unsigned char i = 100;
96
97         mmc_cmd_r0(cmd, addr_h, addr_l);
98         do
99                 mmc_resp[0] = do_spi(0xff);
100         while (mmc_resp[0] == 0xff && --i);
101         mmc_resp[1] = do_spi(0xff);
102 }
103
104 /* Send a command to the SDcard, a five byte response is expected */
105 static void mmc_cmd_r3(char cmd, unsigned short addr_h, unsigned short addr_l)
106 {
107         unsigned char i = 100;
108
109         mmc_cmd_r0(cmd, addr_h, addr_l);
110         do
111                 mmc_resp[0] = do_spi(0xff);
112         while (mmc_resp[0] == 0xff && --i);
113         mmc_resp[1] = do_spi(0xff);
114         mmc_resp[2] = do_spi(0xff);
115         mmc_resp[3] = do_spi(0xff);
116         mmc_resp[4] = do_spi(0xff);
117 }
118
119 /* Enable the MMC/SD card correctly */
120 unsigned char mmc_init(void)
121 {
122         unsigned short lp;
123
124         /* Set SPI clock .. Might need to be smarter at changing the
125          * SPI clock based on what device is enabled...
126          */
127         SSPCON1 = 0x22; //spiclk = Fosc/64 (init clock 100-400 kHz)
128
129         _M_CD = 0;
130         _M_CS = 1;
131         wait_timer(10);
132
133         _M_CD = 1; /* Enable clock*/
134         _M_CS = 1; /* SDcard Disabled */
135         
136         /* Set SDcard in SPI-Mode, Reset*/
137         /* (10 * 8bits = 80 clockpulses) */
138         for (lp = 0; lp < 10; lp++)
139                 do_spi(0xff);
140
141         /* Delay for a lot of milliseconds (least 16 bus clock cycles) */
142         for (lp=0; lp < 56000; lp++)
143                 ; /* PRAY sdcc doesn't optimize that out !
144                      Should use timer instead ! */
145         wait_timer(10);
146
147         /* SDcard Enabled */
148         _M_CS = 0;
149
150         /* No card detected by default */
151         mmc_card = MMC_CARD_NONE;
152         
153         /* CMD0: Reset all cards to IDLE state */
154         mmc_cmd_r1(CMD0, 0, 0);
155         if (mmc_resp[0] != 0x01) {
156                 pr_debug("No card detected ! (resp=%x)\n", mmc_resp[0]);
157                 goto fail;
158         }
159
160         /* Default to MMC */
161         mmc_card = MMC_CARD_MMC;
162
163         /* Check for SD Card V2 */
164         /* (Voltage 2.7V - 3.6V, 0xaa test pattern) */
165         mmc_cmd_r3(CMD8, 0x0000, 0x01aa);
166         if (!(mmc_resp[0] & 0x04)) {
167                 if (mmc_resp[3] == 0x01 && mmc_resp[4] == 0xaa) {
168                         pr_debug("SD card V2 detected, possible SDHC\n");
169                         mmc_card |= MMC_CARD_SD_RAW_SPEC_2;
170                 } else {
171                         pr_debug("Error detecting SD V2 card\n");
172                         goto fail;
173                 }
174         } else {
175                 /* Check for SD card V1 */
176                 mmc_cmd_r1(CMD55, 0, 0);
177                 mmc_cmd_r1(CMD41, 0, 0);
178                 if (!(mmc_resp[0] & 0x04)) {
179                         pr_debug("SD card V1 detected\n");
180                         mmc_card |= MMC_CARD_SD_RAW_SPEC_1;
181                 } else
182                         pr_debug("MMC-card detected\n");
183         }
184         
185         /* Wait for card to get ready */
186         mmc_timeout = 0;
187         while (1) {
188                 if (mmc_card & (MMC_CARD_SD_RAW_SPEC_1 | MMC_CARD_SD_RAW_SPEC_2)) {
189                         /* When SD Card detected */
190                         lp = 0x0;
191                         if (mmc_card & MMC_CARD_SD_RAW_SPEC_2)
192                                 lp = 0x4000;
193                         /* Activate SD card init process */
194                         mmc_cmd_r1(CMD55, 0, 0);
195                         mmc_cmd_r1(CMD41, lp, 0);
196                 } else {
197                         /* Activate the MMC cards init process */
198                         mmc_cmd_r1(CMD1, 0, 0);
199                 }
200                 
201                 /* Check if card is idle */
202                 if (mmc_resp[0] == 0x00)
203                         break;
204                 mmc_timeout++;
205                 if (mmc_timeout == 1000) {
206                         pr_debug("SD/MMC ACMD41/CMD1 response timeout...\n");
207                         goto fail;
208                 }
209         }
210
211         /* Check for SDHC card */
212         if (mmc_card & MMC_CARD_SD_RAW_SPEC_2) {
213                 /* Get operating conditions */
214                 mmc_cmd_r3(CMD58, 0, 0);
215                 if (mmc_resp[0]) {
216                         pr_debug("SD/MMC: Failed to get operating conditions\n");
217                         goto fail;
218                 }
219                 
220                 if (mmc_resp[1] & 0x40) {       
221                         pr_debug("SDHC Card Detected\n");
222                         mmc_card |= MMC_CARD_SD_RAW_SPEC_SDHC;
223                 }
224         }
225
226         /* Set block size to 512 bytes */
227         mmc_timeout = 0;
228         while(1) {
229                 mmc_cmd_r1(CMD16, 0x0000, 0x0200);
230                 if (!mmc_resp[0])
231                         break;
232                 mmc_timeout++;
233                 if(mmc_timeout == 100) {
234                         pr_debug("Set block size to 512 timeout\n");
235                         goto fail;
236                 }
237         }
238         
239         spi_disable_sdcard();
240         
241         /* XXX Stuff below from minimig... it's strange... it sets SSPCON1 to a
242          * different speed from what is done in hardware_init.c for everybody
243          */
244         // TODO: Change speed for card access
245         SSPCON1 = 0x20; //spiclk = Fosc/4 (5 MHz)
246         return true;
247  fail:
248         mmc_card = MMC_CARD_NONE;
249         spi_disable_sdcard();
250         return false;
251 }
252
253 /* Read single block (with block-size set by CMD16 to 512 by default) */
254 unsigned char mmc_read(unsigned long lba, unsigned char *out_data)
255 {
256         unsigned short upper_lba, lower_lba;
257         unsigned char i;
258         unsigned char *p;
259
260         /* !SDHC uses byte address instead of LBA */
261         if (!(mmc_card & MMC_CARD_SD_RAW_SPEC_SDHC))
262                 lba <<= 9;
263
264         pr_debug("SD/MMC: Reading LBA 0x%lx\n", lba);
265         
266         upper_lba = (unsigned short)(lba>>16);
267         lower_lba = (unsigned short)lba;
268
269         spi_enable_sdcard();
270
271         mmc_cmd_r1(CMD17, upper_lba, lower_lba);
272
273         /* Exit if invalid response*/
274         if (mmc_resp[0]) {
275                 pr_debug("SD/MMC CMD17: invalid response %x\n", mmc_resp[0]);
276                 goto fail;
277         }
278
279         /* Wait for start of data transfer with timeout */
280         mmc_timeout = 0;
281         while(do_spi(0xff) != 0xfe) {
282                 if (mmc_timeout++ >= 50000) {
283                         pr_debug("SD/MMC CMD17: no data token\n");
284                         goto fail;
285                 }
286         }
287
288         /* Read data and exit OK */
289         p = out_data;
290         for (i = 0; i < 128; i++) {
291                 SSPBUF = 0xff;
292                 while (!SSPSTATbits.BF)
293                         ;
294                 *(p++) = SSPBUF;
295                 SSPBUF = 0xff;
296                 while (!SSPSTATbits.BF)
297                         ;
298                 *(p++) = SSPBUF;
299                 SSPBUF = 0xff;
300                 while (!SSPSTATbits.BF)
301                         ;
302                 *(p++) = SSPBUF;
303                 SSPBUF = 0xff;
304                 while (!SSPSTATbits.BF)
305                         ;
306                 *(p++) = SSPBUF;
307         }
308
309         /* XXX Todo: check CRC */
310         do_spi(0xff);   //Read CRC lo byte
311         do_spi(0xff);   //Read CRC hi byte
312
313         spi_disable_sdcard();
314         return true;
315  fail:
316         spi_disable_sdcard();
317         return false;
318 }
319
320
321
322 /* Write: 512 Byte-Mode, this will not work (read MMC and SD-card specs) with any other
323  * sector/block size
324  */
325 unsigned char mmc_write(unsigned long lba, unsigned char *in_data)
326 {
327         unsigned short upper_lba, lower_lba;
328         unsigned char i;
329         unsigned char *p;
330
331         /* !SDHC uses byte address instead of LBA */
332         if (!(mmc_card & MMC_CARD_SD_RAW_SPEC_SDHC))
333                 lba <<= 9;
334
335         pr_debug("SD/MMC: Writing LBA 0x%lx\n", lba);
336
337         upper_lba = (unsigned short)(lba>>16);
338         lower_lba = (unsigned short)lba;
339
340         spi_enable_sdcard();
341
342         mmc_cmd_r1(CMD24, upper_lba, lower_lba);
343
344         /* Exit if invalid response*/
345         if (mmc_resp[0]) {
346                 pr_debug("SD/MMC CMD24: invalid response %x\n", mmc_resp[0]);
347                 goto fail;
348         }
349
350         do_spi(0xff);   //One byte gap
351         do_spi(0xfe);   //Send Data token
352
353         /* Send bytes for sector */
354         p = in_data;
355         for (i = 0; i < 128; i++) {
356                 SSPBUF = *(p++);
357                 while (!SSPSTATbits.BF)
358                         ;
359                 SSPBUF = *(p++);
360                 while (!SSPSTATbits.BF)
361                         ;
362                 SSPBUF = *(p++);
363                 while (!SSPSTATbits.BF)
364                         ;
365                 SSPBUF = *(p++);
366                 while (!SSPSTATbits.BF)
367                         ;
368         }
369
370         /* XXX Todo: Send proper CRC ? */
371         do_spi(0xff);   //Send CRC lo byte
372         do_spi(0xff);   //Send CRC hi byte
373
374         /* Read packet response */
375         i = do_spi(0xff);
376
377         /* Status codes
378          *  010 = Data accepted
379          *  101 = Data rejected due to CRC error
380          *  110 = Data rejected due to write error
381          */
382         i &= 0b00011111;
383         if (i != 0b00000101) {
384                 pr_debug("SD/MMC CMD24: write error %x\n", i);
385                 goto fail;
386         }
387
388         mmc_timeout = 0;
389         /* Wait until the card has finished writing the data */
390         while (do_spi(0xff) == 0x00) {
391                 if (mmc_timeout++ >= 50000) {
392                         pr_debug("SD/MMC CMD24: busy wait timeout\n");
393                         goto fail;
394                 }
395         }
396         spi_disable_sdcard();
397         return true;
398  fail:
399         spi_disable_sdcard();
400         return false;
401 }
402