Root/
Source at commit ee76fb4f890f40f18832f5f0e93213a995efb17c created 13 years 5 months ago. By Xiangfu Liu, remove useless functions in jz_mmc.c: mmc_block_write, mmc_write, mmc_ident, mmc2info | |
---|---|
1 | /* |
2 | * (C) Copyright 2003 |
3 | * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net |
4 | * |
5 | * See file CREDITS for list of people who contributed to this |
6 | * project. |
7 | * |
8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License as |
10 | * published by the Free Software Foundation; either version 2 of |
11 | * the License, or (at your option) any later version. |
12 | * |
13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
21 | * MA 02111-1307 USA |
22 | */ |
23 | |
24 | #include <config.h> |
25 | #include <common.h> |
26 | #include <part.h> |
27 | #include <mmc.h> |
28 | |
29 | #include <asm/jz4740.h> |
30 | #include "jz_mmc.h" |
31 | |
32 | #define CFG_MMC_BASE 0x80600000 |
33 | static int sd2_0 = 0; |
34 | static uchar mmc_buf[1024]; |
35 | static int mmc_ready = 0; |
36 | static int use_4bit; /* Use 4-bit data bus */ |
37 | /* |
38 | * MMC Events |
39 | */ |
40 | #define MMC_EVENT_NONE 0x00 /* No events */ |
41 | #define MMC_EVENT_RX_DATA_DONE 0x01 /* Rx data done */ |
42 | #define MMC_EVENT_TX_DATA_DONE 0x02 /* Tx data done */ |
43 | #define MMC_EVENT_PROG_DONE 0x04 /* Programming is done */ |
44 | |
45 | |
46 | #define MMC_IRQ_MASK() \ |
47 | do { \ |
48 | REG_MSC_IMASK = 0xffff; \ |
49 | REG_MSC_IREG = 0xffff; \ |
50 | } while (0) |
51 | |
52 | /* |
53 | * GPIO definition |
54 | */ |
55 | #if defined(CONFIG_SAKC) |
56 | |
57 | #define __msc_init_io() \ |
58 | do { \ |
59 | __gpio_as_input(GPIO_SD_CD_N); \ |
60 | } while (0) |
61 | |
62 | #else |
63 | #define __msc_init_io() \ |
64 | do { \ |
65 | __gpio_as_output(GPIO_SD_VCC_EN_N); \ |
66 | __gpio_as_input(GPIO_SD_CD_N); \ |
67 | } while (0) |
68 | |
69 | #define __msc_enable_power() \ |
70 | do { \ |
71 | __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ |
72 | } while (0) |
73 | |
74 | #define __msc_disable_power() \ |
75 | do { \ |
76 | __gpio_set_pin(GPIO_SD_VCC_EN_N); \ |
77 | } while (0) |
78 | |
79 | #endif /* CONFIG_SAKE */ |
80 | |
81 | #define __msc_card_detected() \ |
82 | ({ \ |
83 | int detected = 1; \ |
84 | __gpio_as_input(GPIO_SD_CD_N); \ |
85 | __gpio_disable_pull(GPIO_SD_CD_N); \ |
86 | if (!__gpio_get_pin(GPIO_SD_CD_N)) \ |
87 | detected = 0; \ |
88 | detected; \ |
89 | }) |
90 | |
91 | /* |
92 | * Local functions |
93 | */ |
94 | |
95 | extern int |
96 | fat_register_device(block_dev_desc_t *dev_desc, int part_no); |
97 | |
98 | static block_dev_desc_t mmc_dev; |
99 | |
100 | block_dev_desc_t * mmc_get_dev(int dev) |
101 | { |
102 | return ((block_dev_desc_t *)&mmc_dev); |
103 | } |
104 | |
105 | /* Stop the MMC clock and wait while it happens */ |
106 | static inline int jz_mmc_stop_clock(void) |
107 | { |
108 | int timeout = 1000; |
109 | |
110 | REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; |
111 | |
112 | while (timeout && (REG_MSC_STAT & MSC_STAT_CLK_EN)) { |
113 | timeout--; |
114 | if (timeout == 0) |
115 | return MMC_ERROR_TIMEOUT; |
116 | udelay(1); |
117 | } |
118 | return MMC_NO_ERROR; |
119 | } |
120 | |
121 | /* Start the MMC clock and operation */ |
122 | static inline int jz_mmc_start_clock(void) |
123 | { |
124 | REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START | MSC_STRPCL_START_OP; |
125 | return MMC_NO_ERROR; |
126 | } |
127 | |
128 | static inline u32 jz_mmc_calc_clkrt(int is_sd, u32 rate) |
129 | { |
130 | u32 clkrt = 0; |
131 | u32 clk_src = is_sd ? 24000000 : 16000000; |
132 | |
133 | while (rate < clk_src) { |
134 | clkrt ++; |
135 | clk_src >>= 1; |
136 | } |
137 | |
138 | return clkrt; |
139 | } |
140 | |
141 | /* Set the MMC clock frequency */ |
142 | void jz_mmc_set_clock(int sd, u32 rate) |
143 | { |
144 | jz_mmc_stop_clock(); |
145 | |
146 | /* Select clock source of MSC */ |
147 | __cpm_select_msc_clk(sd); |
148 | |
149 | /* Set clock dividor of MSC */ |
150 | REG_MSC_CLKRT = jz_mmc_calc_clkrt(sd, rate); |
151 | } |
152 | |
153 | static int jz_mmc_check_status(struct mmc_request *request) |
154 | { |
155 | u32 status = REG_MSC_STAT; |
156 | |
157 | /* Checking for response or data timeout */ |
158 | if (status & (MSC_STAT_TIME_OUT_RES | MSC_STAT_TIME_OUT_READ)) { |
159 | printf("MMC/SD timeout, MMC_STAT 0x%x CMD %d\n", status, request->cmd); |
160 | return MMC_ERROR_TIMEOUT; |
161 | } |
162 | |
163 | /* Checking for CRC error */ |
164 | if (status & (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_RES_ERR)) { |
165 | printf("MMC/CD CRC error, MMC_STAT 0x%x\n", status); |
166 | return MMC_ERROR_CRC; |
167 | } |
168 | |
169 | return MMC_NO_ERROR; |
170 | } |
171 | |
172 | /* Obtain response to the command and store it to response buffer */ |
173 | static void jz_mmc_get_response(struct mmc_request *request) |
174 | { |
175 | int i; |
176 | u8 *buf; |
177 | u32 data; |
178 | |
179 | debug("fetch response for request %d, cmd %d\n", |
180 | request->rtype, request->cmd); |
181 | |
182 | buf = request->response; |
183 | request->result = MMC_NO_ERROR; |
184 | |
185 | switch (request->rtype) { |
186 | case RESPONSE_R1: case RESPONSE_R1B: case RESPONSE_R6: |
187 | case RESPONSE_R3: case RESPONSE_R4: case RESPONSE_R5: |
188 | { |
189 | data = REG_MSC_RES; |
190 | buf[0] = (data >> 8) & 0xff; |
191 | buf[1] = data & 0xff; |
192 | data = REG_MSC_RES; |
193 | buf[2] = (data >> 8) & 0xff; |
194 | buf[3] = data & 0xff; |
195 | data = REG_MSC_RES; |
196 | buf[4] = data & 0xff; |
197 | |
198 | debug("request %d, response [%02x %02x %02x %02x %02x]\n", |
199 | request->rtype, buf[0], buf[1], buf[2], buf[3], buf[4]); |
200 | break; |
201 | } |
202 | case RESPONSE_R2_CID: case RESPONSE_R2_CSD: |
203 | { |
204 | for (i = 0; i < 16; i += 2) { |
205 | data = REG_MSC_RES; |
206 | buf[i] = (data >> 8) & 0xff; |
207 | buf[i+1] = data & 0xff; |
208 | } |
209 | debug("request %d, response [", request->rtype); |
210 | #if CONFIG_MMC_DEBUG_VERBOSE > 2 |
211 | if (g_mmc_debug >= 3) { |
212 | int n; |
213 | for (n = 0; n < 17; n++) |
214 | printk("%02x ", buf[n]); |
215 | printk("]\n"); |
216 | } |
217 | #endif |
218 | break; |
219 | } |
220 | case RESPONSE_NONE: |
221 | debug("No response\n"); |
222 | break; |
223 | |
224 | default: |
225 | debug("unhandled response type for request %d\n", request->rtype); |
226 | break; |
227 | } |
228 | } |
229 | |
230 | static int jz_mmc_receive_data(struct mmc_request *req) |
231 | { |
232 | u32 stat, timeout, data, cnt; |
233 | u8 *buf = req->buffer; |
234 | u32 wblocklen = (u32)(req->block_len + 3) >> 2; /* length in word */ |
235 | |
236 | timeout = 0x3ffffff; |
237 | |
238 | while (timeout) { |
239 | timeout--; |
240 | stat = REG_MSC_STAT; |
241 | |
242 | if (stat & MSC_STAT_TIME_OUT_READ) |
243 | return MMC_ERROR_TIMEOUT; |
244 | else if (stat & MSC_STAT_CRC_READ_ERROR) |
245 | return MMC_ERROR_CRC; |
246 | else if (!(stat & MSC_STAT_DATA_FIFO_EMPTY) |
247 | || (stat & MSC_STAT_DATA_FIFO_AFULL)) { |
248 | /* Ready to read data */ |
249 | break; |
250 | } |
251 | udelay(1); |
252 | } |
253 | if (!timeout) |
254 | return MMC_ERROR_TIMEOUT; |
255 | |
256 | /* Read data from RXFIFO. It could be FULL or PARTIAL FULL */ |
257 | cnt = wblocklen; |
258 | while (cnt) { |
259 | data = REG_MSC_RXFIFO; |
260 | { |
261 | *buf++ = (u8)(data >> 0); |
262 | *buf++ = (u8)(data >> 8); |
263 | *buf++ = (u8)(data >> 16); |
264 | *buf++ = (u8)(data >> 24); |
265 | } |
266 | cnt --; |
267 | while (cnt && (REG_MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY)) |
268 | ; |
269 | } |
270 | return MMC_NO_ERROR; |
271 | } |
272 | |
273 | static int jz_mmc_transmit_data(struct mmc_request *req) |
274 | { |
275 | #if 0 |
276 | u32 nob = req->nob; |
277 | u32 wblocklen = (u32)(req->block_len + 3) >> 2; /* length in word */ |
278 | u8 *buf = req->buffer; |
279 | u32 *wbuf = (u32 *)buf; |
280 | u32 waligned = (((u32)buf & 0x3) == 0); /* word aligned ? */ |
281 | u32 stat, timeout, data, cnt; |
282 | |
283 | for (nob; nob >= 1; nob--) { |
284 | timeout = 0x3FFFFFF; |
285 | |
286 | while (timeout) { |
287 | timeout--; |
288 | stat = REG_MSC_STAT; |
289 | |
290 | if (stat & (MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_WRITE_ERROR_NOSTS)) |
291 | return MMC_ERROR_CRC; |
292 | else if (!(stat & MSC_STAT_DATA_FIFO_FULL)) { |
293 | /* Ready to write data */ |
294 | break; |
295 | } |
296 | |
297 | udelay(1); |
298 | } |
299 | |
300 | if (!timeout) |
301 | return MMC_ERROR_TIMEOUT; |
302 | |
303 | /* Write data to TXFIFO */ |
304 | cnt = wblocklen; |
305 | while (cnt) { |
306 | while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_FULL) |
307 | ; |
308 | |
309 | if (waligned) { |
310 | REG_MSC_TXFIFO = *wbuf++; |
311 | } |
312 | else { |
313 | data = *buf++ | (*buf++ << 8) | (*buf++ << 16) | (*buf++ << 24); |
314 | REG_MSC_TXFIFO = data; |
315 | } |
316 | |
317 | cnt--; |
318 | } |
319 | } |
320 | #endif |
321 | return MMC_NO_ERROR; |
322 | } |
323 | |
324 | |
325 | /* |
326 | * Name: int jz_mmc_exec_cmd() |
327 | * Function: send command to the card, and get a response |
328 | * Input: struct mmc_request *req : MMC/SD request |
329 | * Output: 0: right >0: error code |
330 | */ |
331 | int jz_mmc_exec_cmd(struct mmc_request *request) |
332 | { |
333 | u32 cmdat = 0, events = 0; |
334 | int retval, timeout = 0x3fffff; |
335 | |
336 | /* Indicate we have no result yet */ |
337 | request->result = MMC_NO_RESPONSE; |
338 | if (request->cmd == MMC_CIM_RESET) { |
339 | /* On reset, 1-bit bus width */ |
340 | use_4bit = 0; |
341 | |
342 | /* Reset MMC/SD controller */ |
343 | __msc_reset(); |
344 | |
345 | /* On reset, drop MMC clock down */ |
346 | jz_mmc_set_clock(0, MMC_CLOCK_SLOW); |
347 | |
348 | /* On reset, stop MMC clock */ |
349 | jz_mmc_stop_clock(); |
350 | } |
351 | if (request->cmd == MMC_CMD_SEND_OP_COND) { |
352 | debug("Have an MMC card\n"); |
353 | /* always use 1bit for MMC */ |
354 | use_4bit = 0; |
355 | } |
356 | if (request->cmd == SET_BUS_WIDTH) { |
357 | if (request->arg == 0x2) { |
358 | printf("Use 4-bit bus width\n"); |
359 | use_4bit = 1; |
360 | } else { |
361 | printf("Use 1-bit bus width\n"); |
362 | use_4bit = 0; |
363 | } |
364 | } |
365 | |
366 | /* stop clock */ |
367 | jz_mmc_stop_clock(); |
368 | |
369 | /* mask all interrupts */ |
370 | REG_MSC_IMASK = 0xffff; |
371 | |
372 | /* clear status */ |
373 | REG_MSC_IREG = 0xffff; |
374 | |
375 | /* use 4-bit bus width when possible */ |
376 | if (use_4bit) |
377 | cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT; |
378 | |
379 | /* Set command type and events */ |
380 | switch (request->cmd) { |
381 | /* MMC core extra command */ |
382 | case MMC_CIM_RESET: |
383 | cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */ |
384 | break; |
385 | |
386 | /* bc - broadcast - no response */ |
387 | case MMC_CMD_GO_IDLE_STATE: |
388 | case MMC_CMD_SET_DSR: |
389 | break; |
390 | |
391 | /* bcr - broadcast with response */ |
392 | case MMC_CMD_SEND_OP_COND: |
393 | case MMC_CMD_ALL_SEND_CID: |
394 | case MMC_GO_IRQ_STATE: |
395 | break; |
396 | |
397 | /* adtc - addressed with data transfer */ |
398 | case MMC_READ_DAT_UNTIL_STOP: |
399 | case MMC_CMD_READ_SINGLE_BLOCK: |
400 | case MMC_CMD_READ_MULTIPLE_BLOCK: |
401 | case SD_CMD_APP_SEND_SCR: |
402 | cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ; |
403 | events = MMC_EVENT_RX_DATA_DONE; |
404 | break; |
405 | |
406 | case MMC_WRITE_DAT_UNTIL_STOP: |
407 | case MMC_CMD_WRITE_SINGLE_BLOCK: |
408 | case MMC_CMD_WRITE_MULTIPLE_BLOCK: |
409 | case MMC_PROGRAM_CID: |
410 | case MMC_PROGRAM_CSD: |
411 | case MMC_SEND_WRITE_PROT: |
412 | case MMC_GEN_CMD: |
413 | case MMC_LOCK_UNLOCK: |
414 | cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE; |
415 | events = MMC_EVENT_TX_DATA_DONE | MMC_EVENT_PROG_DONE; |
416 | |
417 | break; |
418 | |
419 | case MMC_CMD_STOP_TRANSMISSION: |
420 | events = MMC_EVENT_PROG_DONE; |
421 | break; |
422 | |
423 | /* ac - no data transfer */ |
424 | default: |
425 | break; |
426 | } |
427 | |
428 | /* Set response type */ |
429 | switch (request->rtype) { |
430 | case RESPONSE_NONE: |
431 | break; |
432 | |
433 | case RESPONSE_R1B: |
434 | cmdat |= MSC_CMDAT_BUSY; |
435 | /*FALLTHRU*/ |
436 | case RESPONSE_R1: |
437 | cmdat |= MSC_CMDAT_RESPONSE_R1; |
438 | break; |
439 | case RESPONSE_R2_CID: |
440 | case RESPONSE_R2_CSD: |
441 | cmdat |= MSC_CMDAT_RESPONSE_R2; |
442 | break; |
443 | case RESPONSE_R3: |
444 | cmdat |= MSC_CMDAT_RESPONSE_R3; |
445 | break; |
446 | case RESPONSE_R4: |
447 | cmdat |= MSC_CMDAT_RESPONSE_R4; |
448 | break; |
449 | case RESPONSE_R5: |
450 | cmdat |= MSC_CMDAT_RESPONSE_R5; |
451 | break; |
452 | case RESPONSE_R6: |
453 | cmdat |= MSC_CMDAT_RESPONSE_R6; |
454 | break; |
455 | default: |
456 | break; |
457 | } |
458 | |
459 | /* Set command index */ |
460 | if (request->cmd == MMC_CIM_RESET) { |
461 | REG_MSC_CMD = MMC_CMD_GO_IDLE_STATE; |
462 | } else { |
463 | REG_MSC_CMD = request->cmd; |
464 | } |
465 | |
466 | /* Set argument */ |
467 | REG_MSC_ARG = request->arg; |
468 | |
469 | /* Set block length and nob */ |
470 | if (request->cmd == SD_CMD_APP_SEND_SCR) { /* get SCR from DataFIFO */ |
471 | REG_MSC_BLKLEN = 8; |
472 | REG_MSC_NOB = 1; |
473 | } else { |
474 | REG_MSC_BLKLEN = request->block_len; |
475 | REG_MSC_NOB = request->nob; |
476 | } |
477 | |
478 | /* Set command */ |
479 | REG_MSC_CMDAT = cmdat; |
480 | |
481 | debug("Send cmd %d cmdat: %x arg: %x resp %d\n", request->cmd, |
482 | cmdat, request->arg, request->rtype); |
483 | |
484 | /* Start MMC/SD clock and send command to card */ |
485 | jz_mmc_start_clock(); |
486 | |
487 | /* Wait for command completion */ |
488 | while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES)) |
489 | ; |
490 | |
491 | if (timeout == 0) |
492 | return MMC_ERROR_TIMEOUT; |
493 | |
494 | REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear flag */ |
495 | |
496 | /* Check for status */ |
497 | retval = jz_mmc_check_status(request); |
498 | if (retval) { |
499 | return retval; |
500 | } |
501 | |
502 | /* Complete command with no response */ |
503 | if (request->rtype == RESPONSE_NONE) { |
504 | return MMC_NO_ERROR; |
505 | } |
506 | |
507 | /* Get response */ |
508 | jz_mmc_get_response(request); |
509 | |
510 | /* Start data operation */ |
511 | if (events & (MMC_EVENT_RX_DATA_DONE | MMC_EVENT_TX_DATA_DONE)) { |
512 | if (events & MMC_EVENT_RX_DATA_DONE) { |
513 | if (request->cmd == SD_CMD_APP_SEND_SCR) { |
514 | /* SD card returns SCR register as data. |
515 | MMC core expect it in the response buffer, |
516 | after normal response. */ |
517 | request->buffer = (u8 *)((u32)request->response + 5); |
518 | } |
519 | jz_mmc_receive_data(request); |
520 | } |
521 | |
522 | if (events & MMC_EVENT_TX_DATA_DONE) { |
523 | jz_mmc_transmit_data(request); |
524 | } |
525 | |
526 | /* Wait for Data Done */ |
527 | while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE)) |
528 | ; |
529 | REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */ |
530 | } |
531 | |
532 | /* Wait for Prog Done event */ |
533 | if (events & MMC_EVENT_PROG_DONE) { |
534 | while (!(REG_MSC_IREG & MSC_IREG_PRG_DONE)) |
535 | ; |
536 | REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */ |
537 | } |
538 | |
539 | /* Command completed */ |
540 | |
541 | return MMC_NO_ERROR; /* return successfully */ |
542 | } |
543 | |
544 | int mmc_block_read(u8 *dst, ulong src, ulong len) |
545 | { |
546 | |
547 | struct mmc_request request; |
548 | struct mmc_response_r1 r1; |
549 | int retval = 0; |
550 | |
551 | if (len == 0) |
552 | goto exit; |
553 | |
554 | mmc_simple_cmd(&request, MMC_CMD_SEND_STATUS, mmcinfo.rca, RESPONSE_R1); |
555 | retval = mmc_unpack_r1(&request, &r1, 0); |
556 | if (retval && (retval != MMC_ERROR_STATE_MISMATCH)) |
557 | goto exit; |
558 | |
559 | mmc_simple_cmd(&request, MMC_CMD_SET_BLOCKLEN, len, RESPONSE_R1); |
560 | if (retval = mmc_unpack_r1(&request, &r1, 0)) |
561 | goto exit; |
562 | |
563 | if (sd2_0) |
564 | src /= len; |
565 | |
566 | mmc_send_cmd(&request, MMC_CMD_READ_SINGLE_BLOCK, src, 1, len, RESPONSE_R1, dst); |
567 | if (retval = mmc_unpack_r1(&request, &r1, 0)) |
568 | goto exit; |
569 | |
570 | exit: |
571 | return retval; |
572 | } |
573 | |
574 | ulong mmc_bread(int dev_num, ulong blkstart, ulong blkcnt, ulong *dst) |
575 | { |
576 | if (!mmc_ready) { |
577 | printf("Please initial the MMC first\n"); |
578 | return -1; |
579 | } |
580 | |
581 | int i = 0; |
582 | ulong src = blkstart * mmcinfo.block_len; |
583 | ulong dst_tmp = dst; |
584 | |
585 | for (i = 0; i < blkcnt; i++) { |
586 | if ((mmc_block_read((uchar *)(dst_tmp), src, mmcinfo.block_len)) < 0) |
587 | return -1; |
588 | |
589 | dst_tmp += mmcinfo.block_len; |
590 | src += mmcinfo.block_len; |
591 | } |
592 | |
593 | return i; |
594 | } |
595 | |
596 | int mmc_select_card(void) |
597 | { |
598 | struct mmc_request request; |
599 | struct mmc_response_r1 r1; |
600 | int retval; |
601 | |
602 | mmc_simple_cmd(&request, MMC_CMD_SELECT_CARD, mmcinfo.rca, RESPONSE_R1B); |
603 | retval = mmc_unpack_r1(&request, &r1, 0); |
604 | if (retval) { |
605 | return retval; |
606 | } |
607 | |
608 | if (mmcinfo.sd) { |
609 | mmc_simple_cmd(&request, MMC_CMD_APP_CMD, mmcinfo.rca, RESPONSE_R1); |
610 | retval = mmc_unpack_r1(&request,&r1,0); |
611 | if (retval) { |
612 | return retval; |
613 | } |
614 | #if defined(MMC_BUS_WIDTH_1BIT) |
615 | mmc_simple_cmd(&request, SET_BUS_WIDTH, 1, RESPONSE_R1); |
616 | #else |
617 | mmc_simple_cmd(&request, SET_BUS_WIDTH, 2, RESPONSE_R1); |
618 | #endif |
619 | retval = mmc_unpack_r1(&request,&r1,0); |
620 | if (retval) { |
621 | return retval; |
622 | } |
623 | } |
624 | return 0; |
625 | } |
626 | |
627 | /* |
628 | * Configure card |
629 | */ |
630 | static void mmc_configure_card(void) |
631 | { |
632 | u32 rate; |
633 | |
634 | /* Get card info */ |
635 | if (sd2_0) |
636 | mmcinfo.block_num = (mmcinfo.csd.c_size + 1) << 10; |
637 | else |
638 | mmcinfo.block_num = (mmcinfo.csd.c_size + 1) * (1 << (mmcinfo.csd.c_size_mult + 2)); |
639 | |
640 | mmcinfo.block_len = 1 << mmcinfo.csd.read_bl_len; |
641 | |
642 | mmc_dev.if_type = IF_TYPE_SD; |
643 | mmc_dev.part_type = PART_TYPE_DOS; |
644 | mmc_dev.dev = 0; |
645 | mmc_dev.lun = 0; |
646 | mmc_dev.type = 0; |
647 | mmc_dev.blksz = mmcinfo.block_len; |
648 | mmc_dev.lba = mmcinfo.block_num; |
649 | mmc_dev.removable = 0; |
650 | |
651 | printf("%s Detected: %lu blocks of %lu bytes\n", |
652 | sd2_0 == 1 ? "SDHC" : "SD", |
653 | mmc_dev.lba, |
654 | mmc_dev.blksz); |
655 | |
656 | /* Fix the clock rate */ |
657 | rate = mmc_tran_speed(mmcinfo.csd.tran_speed); |
658 | if (rate < MMC_CLOCK_SLOW) |
659 | rate = MMC_CLOCK_SLOW; |
660 | if ((mmcinfo.sd == 0) && (rate > MMC_CLOCK_FAST)) |
661 | rate = MMC_CLOCK_FAST; |
662 | if ((mmcinfo.sd) && (rate > SD_CLOCK_FAST)) |
663 | rate = SD_CLOCK_FAST; |
664 | |
665 | debug("%s: block_len=%d block_num=%d rate=%d\n", |
666 | __func__, mmcinfo.block_len, mmcinfo.block_num, rate); |
667 | |
668 | jz_mmc_set_clock(mmcinfo.sd, rate); |
669 | } |
670 | |
671 | /* |
672 | * State machine routines to initialize card(s) |
673 | */ |
674 | |
675 | /* |
676 | CIM_SINGLE_CARD_ACQ (frequency at 400 kHz) |
677 | --- Must enter from GO_IDLE_STATE --- |
678 | 1. SD_SEND_OP_COND (SD Card) [CMD55] + [CMD41] |
679 | 2. SEND_OP_COND (Full Range) [CMD1] {optional} |
680 | 3. SEND_OP_COND (Set Range ) [CMD1] |
681 | If busy, delay and repeat step 2 |
682 | 4. ALL_SEND_CID [CMD2] |
683 | If timeout, set an error (no cards found) |
684 | 5. SET_RELATIVE_ADDR [CMD3] |
685 | 6. SEND_CSD [CMD9] |
686 | 7. SET_DSR [CMD4] Only call this if (csd.dsr_imp). |
687 | 8. Set clock frequency (check available in csd.tran_speed) |
688 | */ |
689 | |
690 | #define MMC_INIT_DOING 0 |
691 | #define MMC_INIT_PASSED 1 |
692 | #define MMC_INIT_FAILED 2 |
693 | |
694 | static int mmc_init_card_state(struct mmc_request *request) |
695 | { |
696 | struct mmc_response_r1 r1; |
697 | struct mmc_response_r3 r3; |
698 | int retval; |
699 | int ocr = 0x40300000; |
700 | int limit_41 = 0; |
701 | |
702 | switch (request->cmd) { |
703 | case MMC_CMD_GO_IDLE_STATE: /* No response to parse */ |
704 | if (mmcinfo.sd) |
705 | mmc_simple_cmd(request, 8, 0x1aa, RESPONSE_R1); |
706 | else |
707 | mmc_simple_cmd(request, MMC_CMD_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3); |
708 | break; |
709 | |
710 | case 8: |
711 | retval = mmc_unpack_r1(request,&r1,mmcinfo.state); |
712 | mmc_simple_cmd(request, MMC_CMD_APP_CMD, 0, RESPONSE_R1); |
713 | break; |
714 | |
715 | case MMC_CMD_APP_CMD: |
716 | retval = mmc_unpack_r1(request,&r1,mmcinfo.state); |
717 | if (retval & (limit_41 < 100)) { |
718 | debug("%s: unable to MMC_APP_CMD error=%d (%s)\n", |
719 | __func__, retval, mmc_result_to_string(retval)); |
720 | limit_41++; |
721 | mmc_simple_cmd(request, SD_CMD_APP_SEND_OP_COND, ocr, RESPONSE_R3); |
722 | } else if (limit_41 < 100) { |
723 | limit_41++; |
724 | mmc_simple_cmd(request, SD_CMD_APP_SEND_OP_COND, ocr, RESPONSE_R3); |
725 | } else{ |
726 | /* reset the card to idle*/ |
727 | mmc_simple_cmd(request, MMC_CMD_GO_IDLE_STATE, 0, RESPONSE_NONE); |
728 | mmcinfo.sd = 0; |
729 | } |
730 | break; |
731 | |
732 | case SD_CMD_APP_SEND_OP_COND: |
733 | retval = mmc_unpack_r3(request, &r3); |
734 | if (retval) { |
735 | debug("%s: try MMC card\n", __func__); |
736 | mmc_simple_cmd(request, SD_CMD_APP_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3); |
737 | break; |
738 | } |
739 | |
740 | debug("%s: read ocr value = 0x%08x\n", __func__, r3.ocr); |
741 | |
742 | if(!(r3.ocr & MMC_CARD_BUSY || ocr == 0)){ |
743 | udelay(50000); |
744 | mmc_simple_cmd(request, MMC_CMD_APP_CMD, 0, RESPONSE_R1); |
745 | } else { |
746 | mmcinfo.sd = 1; /* SD Card ready */ |
747 | mmcinfo.state = CARD_STATE_READY; |
748 | mmc_simple_cmd(request, MMC_CMD_ALL_SEND_CID, 0, RESPONSE_R2_CID); |
749 | } |
750 | break; |
751 | |
752 | case MMC_CMD_SEND_OP_COND: |
753 | retval = mmc_unpack_r3(request, &r3); |
754 | if (retval) { |
755 | debug("%s: failed SEND_OP_COND error=%d (%s)\n", |
756 | __func__, retval, mmc_result_to_string(retval)); |
757 | return MMC_INIT_FAILED; |
758 | } |
759 | |
760 | debug("%s: read ocr value = 0x%08x\n", __func__, r3.ocr); |
761 | if (!(r3.ocr & MMC_CARD_BUSY)) { |
762 | mmc_simple_cmd(request, MMC_CMD_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3); |
763 | } else { |
764 | mmcinfo.sd = 0; /* MMC Card ready */ |
765 | mmcinfo.state = CARD_STATE_READY; |
766 | mmc_simple_cmd(request, MMC_CMD_ALL_SEND_CID, 0, RESPONSE_R2_CID); |
767 | } |
768 | break; |
769 | |
770 | case MMC_CMD_ALL_SEND_CID: |
771 | retval = mmc_unpack_cid( request, &mmcinfo.cid ); |
772 | /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */ |
773 | if ( retval && (retval != MMC_ERROR_CRC)) { |
774 | debug("mmc_init_card_state: unable to ALL_SEND_CID error=%d (%s)\n", |
775 | retval, mmc_result_to_string(retval)); |
776 | return MMC_INIT_FAILED; |
777 | } |
778 | mmcinfo.state = CARD_STATE_IDENT; |
779 | if(mmcinfo.sd) |
780 | mmc_simple_cmd(request, MMC_CMD_SET_RELATIVE_ADDR, 0, RESPONSE_R6); |
781 | else |
782 | mmc_simple_cmd(request, MMC_CMD_SET_RELATIVE_ADDR, ID_TO_RCA(mmcinfo.id) << 16, RESPONSE_R1); |
783 | break; |
784 | |
785 | case MMC_CMD_SET_RELATIVE_ADDR: |
786 | if (mmcinfo.sd) { |
787 | retval = mmc_unpack_r6(request, &r1, mmcinfo.state, &mmcinfo.rca); |
788 | mmcinfo.rca = mmcinfo.rca << 16; |
789 | debug("%s: Get RCA from SD: 0x%04x Status: %x\n", |
790 | __func__, mmcinfo.rca, r1.status); |
791 | } else { |
792 | retval = mmc_unpack_r1(request,&r1,mmcinfo.state); |
793 | mmcinfo.rca = ID_TO_RCA(mmcinfo.id) << 16; |
794 | } |
795 | if (retval) { |
796 | debug("%s: unable to SET_RELATIVE_ADDR error=%d (%s)\n", |
797 | __func__, retval, mmc_result_to_string(retval)); |
798 | return MMC_INIT_FAILED; |
799 | } |
800 | |
801 | mmcinfo.state = CARD_STATE_STBY; |
802 | mmc_simple_cmd(request, MMC_CMD_SEND_CSD, mmcinfo.rca, RESPONSE_R2_CSD); |
803 | |
804 | break; |
805 | |
806 | case MMC_CMD_SEND_CSD: |
807 | retval = mmc_unpack_csd(request, &mmcinfo.csd); |
808 | mmc_ready = 1; |
809 | /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */ |
810 | if (retval && (retval != MMC_ERROR_CRC)) { |
811 | debug("%s: unable to SEND_CSD error=%d (%s)\n", |
812 | __func__, retval, mmc_result_to_string(retval)); |
813 | return MMC_INIT_FAILED; |
814 | } |
815 | if (mmcinfo.csd.dsr_imp) { |
816 | debug("%s: driver doesn't support setting DSR\n", __func__); |
817 | } |
818 | mmc_configure_card(); |
819 | return MMC_INIT_PASSED; |
820 | |
821 | default: |
822 | debug("%s: error! Illegal last cmd %d\n", __func__, request->cmd); |
823 | return MMC_INIT_FAILED; |
824 | } |
825 | |
826 | return MMC_INIT_DOING; |
827 | } |
828 | |
829 | int mmc_init_card(void) |
830 | { |
831 | struct mmc_request request; |
832 | int retval; |
833 | |
834 | mmc_simple_cmd(&request, MMC_CIM_RESET, 0, RESPONSE_NONE); /* reset card */ |
835 | mmc_simple_cmd(&request, MMC_CMD_GO_IDLE_STATE, 0, RESPONSE_NONE); |
836 | mmcinfo.sd = 1; /* assuming a SD card */ |
837 | |
838 | while ((retval = mmc_init_card_state(&request)) == MMC_INIT_DOING) |
839 | ; |
840 | |
841 | if (retval == MMC_INIT_PASSED) |
842 | return MMC_NO_ERROR; |
843 | else |
844 | return MMC_NO_RESPONSE; |
845 | } |
846 | |
847 | int mmc_legacy_init(int verbose) |
848 | { |
849 | if (!__msc_card_detected()) |
850 | return 1; |
851 | |
852 | /* Step-1: init GPIO */ |
853 | __gpio_as_msc(); |
854 | __msc_init_io(); |
855 | |
856 | /* Step-2: turn on power of card */ |
857 | #if !defined(CONFIG_SAKC) |
858 | __msc_enable_power(); |
859 | #endif |
860 | |
861 | /* Step-3: Reset MSC Controller. */ |
862 | __msc_reset(); |
863 | |
864 | /* Step-3: mask all IRQs. */ |
865 | MMC_IRQ_MASK(); |
866 | |
867 | /* Step-4: stop MMC/SD clock */ |
868 | jz_mmc_stop_clock(); |
869 | mmc_init_card(); |
870 | mmc_select_card(); |
871 | |
872 | mmc_dev.block_read = mmc_bread; |
873 | fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */ |
874 | |
875 | return 0; |
876 | } |
877 | |
878 | /* |
879 | * Debugging functions |
880 | */ |
881 | static char * mmc_result_strings[] = { |
882 | "NO_RESPONSE", |
883 | "NO_ERROR", |
884 | "ERROR_OUT_OF_RANGE", |
885 | "ERROR_ADDRESS", |
886 | "ERROR_BLOCK_LEN", |
887 | "ERROR_ERASE_SEQ", |
888 | "ERROR_ERASE_PARAM", |
889 | "ERROR_WP_VIOLATION", |
890 | "ERROR_CARD_IS_LOCKED", |
891 | "ERROR_LOCK_UNLOCK_FAILED", |
892 | "ERROR_COM_CRC", |
893 | "ERROR_ILLEGAL_COMMAND", |
894 | "ERROR_CARD_ECC_FAILED", |
895 | "ERROR_CC", |
896 | "ERROR_GENERAL", |
897 | "ERROR_UNDERRUN", |
898 | "ERROR_OVERRUN", |
899 | "ERROR_CID_CSD_OVERWRITE", |
900 | "ERROR_STATE_MISMATCH", |
901 | "ERROR_HEADER_MISMATCH", |
902 | "ERROR_TIMEOUT", |
903 | "ERROR_CRC", |
904 | "ERROR_DRIVER_FAILURE", |
905 | }; |
906 | |
907 | char * mmc_result_to_string(int i) |
908 | { |
909 | return mmc_result_strings[i+1]; |
910 | } |
911 | |
912 | static char * card_state_strings[] = { |
913 | "empty", |
914 | "idle", |
915 | "ready", |
916 | "ident", |
917 | "stby", |
918 | "tran", |
919 | "data", |
920 | "rcv", |
921 | "prg", |
922 | "dis", |
923 | }; |
924 | |
925 | static inline char * card_state_to_string(int i) |
926 | { |
927 | return card_state_strings[i+1]; |
928 | } |
929 | |
930 | /* |
931 | * Utility functions |
932 | */ |
933 | |
934 | #define PARSE_U32(_buf,_index) \ |
935 | (((u32)_buf[_index]) << 24) | (((u32)_buf[_index+1]) << 16) | \ |
936 | (((u32)_buf[_index+2]) << 8) | ((u32)_buf[_index+3]); |
937 | |
938 | #define PARSE_U16(_buf,_index) \ |
939 | (((u16)_buf[_index]) << 8) | ((u16)_buf[_index+1]); |
940 | |
941 | int mmc_unpack_csd(struct mmc_request *request, struct mmc_csd *csd) |
942 | { |
943 | u8 *buf = request->response; |
944 | int num = 0; |
945 | |
946 | if (request->result) |
947 | return request->result; |
948 | |
949 | if (buf[0] != 0x3f) |
950 | return MMC_ERROR_HEADER_MISMATCH; |
951 | |
952 | csd->csd_structure = (buf[1] & 0xc0) >> 6; |
953 | if (csd->csd_structure) |
954 | sd2_0 = 1; |
955 | else |
956 | sd2_0 = 0; |
957 | |
958 | switch (csd->csd_structure) { |
959 | case 0 :/* Version 1.01-1.10 |
960 | * Version 2.00/Standard Capacity */ |
961 | csd->taac = buf[2]; |
962 | csd->nsac = buf[3]; |
963 | csd->tran_speed = buf[4]; |
964 | csd->ccc = (((u16)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4); |
965 | csd->read_bl_len = buf[6] & 0x0f; |
966 | /* for support 2GB card*/ |
967 | if (csd->read_bl_len >= 10) |
968 | { |
969 | num = csd->read_bl_len - 9; |
970 | csd->read_bl_len = 9; |
971 | } |
972 | |
973 | csd->read_bl_partial = (buf[7] & 0x80) ? 1 : 0; |
974 | csd->write_blk_misalign = (buf[7] & 0x40) ? 1 : 0; |
975 | csd->read_blk_misalign = (buf[7] & 0x20) ? 1 : 0; |
976 | csd->dsr_imp = (buf[7] & 0x10) ? 1 : 0; |
977 | csd->c_size = ((((u16)buf[7]) & 0x03) << 10) | (((u16)buf[8]) << 2) | (((u16)buf[9]) & 0xc0) >> 6; |
978 | |
979 | if (num) |
980 | csd->c_size = csd->c_size << num; |
981 | |
982 | |
983 | csd->vdd_r_curr_min = (buf[9] & 0x38) >> 3; |
984 | csd->vdd_r_curr_max = buf[9] & 0x07; |
985 | csd->vdd_w_curr_min = (buf[10] & 0xe0) >> 5; |
986 | csd->vdd_w_curr_max = (buf[10] & 0x1c) >> 2; |
987 | csd->c_size_mult = ((buf[10] & 0x03) << 1) | ((buf[11] & 0x80) >> 7); |
988 | csd->sector_size = (buf[11] & 0x7c) >> 2; |
989 | csd->erase_grp_size = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5); |
990 | csd->wp_grp_size = buf[12] & 0x1f; |
991 | csd->wp_grp_enable = (buf[13] & 0x80) ? 1 : 0; |
992 | csd->default_ecc = (buf[13] & 0x60) >> 5; |
993 | csd->r2w_factor = (buf[13] & 0x1c) >> 2; |
994 | csd->write_bl_len = ((buf[13] & 0x03) << 2) | ((buf[14] & 0xc0) >> 6); |
995 | if (csd->write_bl_len >= 10) |
996 | csd->write_bl_len = 9; |
997 | |
998 | csd->write_bl_partial = (buf[14] & 0x20) ? 1 : 0; |
999 | csd->file_format_grp = (buf[15] & 0x80) ? 1 : 0; |
1000 | csd->copy = (buf[15] & 0x40) ? 1 : 0; |
1001 | csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0; |
1002 | csd->tmp_write_protect = (buf[15] & 0x10) ? 1 : 0; |
1003 | csd->file_format = (buf[15] & 0x0c) >> 2; |
1004 | csd->ecc = buf[15] & 0x03; |
1005 | break; |
1006 | case 1 : /* Version 2.00/High Capacity */ |
1007 | csd->taac = 0; |
1008 | csd->nsac = 0; |
1009 | csd->tran_speed = buf[4]; |
1010 | csd->ccc = (((u16)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4); |
1011 | |
1012 | csd->read_bl_len = 9; |
1013 | csd->read_bl_partial = 0; |
1014 | csd->write_blk_misalign = 0; |
1015 | csd->read_blk_misalign = 0; |
1016 | csd->dsr_imp = (buf[7] & 0x10) ? 1 : 0; |
1017 | csd->c_size = ((((u16)buf[8]) & 0x3f) << 16) | (((u16)buf[9]) << 8) | ((u16)buf[10]) ; |
1018 | csd->sector_size = 0x7f; |
1019 | csd->erase_grp_size = 0; |
1020 | csd->wp_grp_size = 0; |
1021 | csd->wp_grp_enable = 0; |
1022 | csd->default_ecc = (buf[13] & 0x60) >> 5; |
1023 | csd->r2w_factor = 4;/* Unused */ |
1024 | csd->write_bl_len = 9; |
1025 | |
1026 | csd->write_bl_partial = 0; |
1027 | csd->file_format_grp = 0; |
1028 | csd->copy = (buf[15] & 0x40) ? 1 : 0; |
1029 | csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0; |
1030 | csd->tmp_write_protect = (buf[15] & 0x10) ? 1 : 0; |
1031 | csd->file_format = 0; |
1032 | csd->ecc = buf[15] & 0x03; |
1033 | } |
1034 | |
1035 | return 0; |
1036 | } |
1037 | |
1038 | int mmc_unpack_r1(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state) |
1039 | { |
1040 | u8 *buf = request->response; |
1041 | |
1042 | if (request->result) |
1043 | return request->result; |
1044 | |
1045 | r1->cmd = buf[0]; |
1046 | r1->status = PARSE_U32(buf,1); |
1047 | |
1048 | debug("mmc_unpack_r1: cmd=%d status=%08x\n", r1->cmd, r1->status); |
1049 | |
1050 | if (R1_STATUS(r1->status)) { |
1051 | if (r1->status & R1_OUT_OF_RANGE) return MMC_ERROR_OUT_OF_RANGE; |
1052 | if (r1->status & R1_ADDRESS_ERROR) return MMC_ERROR_ADDRESS; |
1053 | if (r1->status & R1_BLOCK_LEN_ERROR) return MMC_ERROR_BLOCK_LEN; |
1054 | if (r1->status & R1_ERASE_SEQ_ERROR) return MMC_ERROR_ERASE_SEQ; |
1055 | if (r1->status & R1_ERASE_PARAM) return MMC_ERROR_ERASE_PARAM; |
1056 | if (r1->status & R1_WP_VIOLATION) return MMC_ERROR_WP_VIOLATION; |
1057 | /*if (r1->status & R1_CARD_IS_LOCKED) return MMC_ERROR_CARD_IS_LOCKED; */ |
1058 | if (r1->status & R1_LOCK_UNLOCK_FAILED) return MMC_ERROR_LOCK_UNLOCK_FAILED; |
1059 | if (r1->status & R1_COM_CRC_ERROR) return MMC_ERROR_COM_CRC; |
1060 | if (r1->status & R1_ILLEGAL_COMMAND) return MMC_ERROR_ILLEGAL_COMMAND; |
1061 | if (r1->status & R1_CARD_ECC_FAILED) return MMC_ERROR_CARD_ECC_FAILED; |
1062 | if (r1->status & R1_CC_ERROR) return MMC_ERROR_CC; |
1063 | if (r1->status & R1_ERROR) return MMC_ERROR_GENERAL; |
1064 | if (r1->status & R1_UNDERRUN) return MMC_ERROR_UNDERRUN; |
1065 | if (r1->status & R1_OVERRUN) return MMC_ERROR_OVERRUN; |
1066 | if (r1->status & R1_CID_CSD_OVERWRITE) return MMC_ERROR_CID_CSD_OVERWRITE; |
1067 | } |
1068 | |
1069 | if (buf[0] != request->cmd) |
1070 | return MMC_ERROR_HEADER_MISMATCH; |
1071 | |
1072 | /* This should be last - it's the least dangerous error */ |
1073 | |
1074 | return 0; |
1075 | } |
1076 | |
1077 | int mmc_unpack_scr(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, u32 *scr) |
1078 | { |
1079 | u8 *buf = request->response; |
1080 | if (request->result) |
1081 | return request->result; |
1082 | |
1083 | *scr = PARSE_U32(buf, 5); /* Save SCR returned by the SD Card */ |
1084 | return mmc_unpack_r1(request, r1, state); |
1085 | |
1086 | } |
1087 | |
1088 | int mmc_unpack_r6(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, int *rca) |
1089 | { |
1090 | u8 *buf = request->response; |
1091 | |
1092 | if (request->result) |
1093 | return request->result; |
1094 | |
1095 | *rca = PARSE_U16(buf,1); /* Save RCA returned by the SD Card */ |
1096 | |
1097 | *(buf+1) = 0; |
1098 | *(buf+2) = 0; |
1099 | |
1100 | return mmc_unpack_r1(request, r1, state); |
1101 | } |
1102 | |
1103 | int mmc_unpack_cid(struct mmc_request *request, struct mmc_cid *cid) |
1104 | { |
1105 | int i; |
1106 | u8 *buf = request->response; |
1107 | |
1108 | if (request->result) |
1109 | return request->result; |
1110 | |
1111 | cid->mid = buf[1]; |
1112 | cid->oid = PARSE_U16(buf,2); |
1113 | for (i = 0 ; i < 5 ; i++) |
1114 | cid->pnm[i] = buf[4+i]; |
1115 | cid->pnm[6] = 0; |
1116 | cid->prv = buf[10]; |
1117 | cid->psn = PARSE_U32(buf,10); |
1118 | cid->mdt = buf[15]; |
1119 | |
1120 | printf("Man %02x OEM 0x%04x \"%s\" %d.%d 0x%08x " |
1121 | "Date %02u/%04u\n", |
1122 | cid->mid, |
1123 | cid->oid, |
1124 | cid->pnm, |
1125 | cid->prv >> 4, |
1126 | cid->prv & 0xf, |
1127 | cid->psn, |
1128 | cid->mdt & 0xf, |
1129 | (cid->mdt >> 4) + 2000); |
1130 | |
1131 | if (buf[0] != 0x3f) |
1132 | return MMC_ERROR_HEADER_MISMATCH; |
1133 | return 0; |
1134 | } |
1135 | |
1136 | int mmc_unpack_r3(struct mmc_request *request, struct mmc_response_r3 *r3) |
1137 | { |
1138 | u8 *buf = request->response; |
1139 | |
1140 | if (request->result) |
1141 | return request->result; |
1142 | |
1143 | r3->ocr = PARSE_U32(buf,1); |
1144 | debug("mmc_unpack_r3: ocr=%08x\n", r3->ocr); |
1145 | |
1146 | if (buf[0] != 0x3f) return MMC_ERROR_HEADER_MISMATCH; |
1147 | return 0; |
1148 | } |
1149 | |
1150 | #define KBPS 1 |
1151 | #define MBPS 1000 |
1152 | |
1153 | static u32 ts_exp[] = { 100*KBPS, 1*MBPS, 10*MBPS, 100*MBPS, 0, 0, 0, 0 }; |
1154 | static u32 ts_mul[] = { 0, 1000, 1200, 1300, 1500, 2000, 2500, 3000, |
1155 | 3500, 4000, 4500, 5000, 5500, 6000, 7000, 8000 }; |
1156 | |
1157 | u32 mmc_tran_speed(u8 ts) |
1158 | { |
1159 | u32 rate = ts_exp[(ts & 0x7)] * ts_mul[(ts & 0x78) >> 3]; |
1160 | |
1161 | if (rate <= 0) { |
1162 | debug("%s: error - unrecognized speed 0x%02x\n", __func__, ts); |
1163 | return 1; |
1164 | } |
1165 | |
1166 | return rate; |
1167 | } |
1168 | |
1169 | void mmc_send_cmd(struct mmc_request *request, int cmd, u32 arg, |
1170 | u16 nob, u16 block_len, enum mmc_rsp_t rtype, u8 *buffer) |
1171 | { |
1172 | request->cmd = cmd; |
1173 | request->arg = arg; |
1174 | request->rtype = rtype; |
1175 | request->nob = nob; |
1176 | request->block_len = block_len; |
1177 | request->buffer = buffer; |
1178 | request->cnt = nob * block_len; |
1179 | |
1180 | jz_mmc_exec_cmd(request); |
1181 | } |
1182 |