Remove card_enable_monitoring() and use a mutex instead. The card_enable_monitoring...
[kugel-rb.git] / firmware / target / arm / s3c2440 / sd-s3c2440.c
blobf4c8a4f599e3d86d062b4a828270ce8964ffbcc1
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2009 by Bob Cousins
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 //#define SD_DEBUG
24 #include "sd.h"
25 #include "system.h"
26 #include <string.h>
27 #include "thread.h"
28 #include "panic.h"
30 #ifdef SD_DEBUG
31 #include "uart-s3c2440.h"
32 #endif
33 #ifdef HAVE_HOTSWAP
34 #include "sdmmc.h"
35 #include "disk.h"
36 #include "fat.h"
37 #endif
38 #include "dma-target.h"
39 #include "system-target.h"
40 #include "led-mini2440.h"
42 /* The configuration method is not very flexible. */
43 #define CARD_NUM_SLOT 0
44 #define NUM_CARDS 2
46 #if NUM_CARDS < NUM_DRIVES
47 #error NUM_CARDS less than NUM_DRIVES
48 #endif
50 #define EC_OK 0
51 #define EC_FAILED 1
52 #define EC_NOCARD 2
53 #define EC_WAIT_STATE_FAILED 3
54 #define EC_POWER_UP 4
55 #define EC_FIFO_WR_EMPTY 5
56 #define EC_FIFO_WR_DONE 6
57 #define EC_TRAN_READ_ENTRY 7
58 #define EC_TRAN_READ_EXIT 8
59 #define EC_TRAN_WRITE_ENTRY 9
60 #define EC_TRAN_WRITE_EXIT 10
61 #define EC_COMMAND 11
62 #define EC_WRITE_PROTECT 12
64 #define MIN_YIELD_PERIOD 1000
65 #define UNALIGNED_NUM_SECTORS 10
66 #define MAX_TRANSFER_ERRORS 10
68 /* command flags for send_cmd */
69 #define MCI_NO_FLAGS (0<<0)
70 #define MCI_RESP (1<<0)
71 #define MCI_LONG_RESP (1<<1)
72 #define MCI_ARG (1<<2)
74 #define INITIAL_CLK 400000 /* Initial clock */
75 #define SD_CLK 24000000 /* Clock for SD cards */
76 #define MMC_CLK 15000000 /* Clock for MMC cards */
78 #define SD_ACTIVE_LED LED4
80 #ifdef SD_DEBUG
81 #define dbgprintf uart_printf
82 #else
83 #define dbgprintf(...)
84 #endif
86 struct sd_card_status
88 int retry;
89 int retry_max;
92 /** static, private data **/
94 /* for compatibility */
95 static long last_disk_activity = -1;
97 static bool initialized = false;
98 static bool sd_enabled = false;
99 static long next_yield = 0;
101 static tCardInfo card_info [NUM_CARDS];
103 #ifdef HAVE_MULTIDRIVE
104 static int curr_card = 0; /* current active card */
105 #if 0
106 static struct sd_card_status sd_status[NUM_CARDS] =
108 #if NUM_CARDS > 1
109 {0, 10},
110 #endif
111 {0, 10}
113 #endif
114 #endif
116 /* Shoot for around 75% usage */
117 static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
118 static const char sd_thread_name[] = "sd";
119 static struct mutex sd_mtx SHAREDBSS_ATTR;
120 static struct event_queue sd_queue;
121 static struct wakeup transfer_completion_signal;
122 static volatile unsigned int transfer_error[NUM_VOLUMES];
123 /* align on cache line size */
124 static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS * SD_BLOCK_SIZE]
125 __attribute__((aligned(32)));
126 static unsigned char * uncached_buffer;
128 static inline void mci_delay(void)
130 int i = 0xffff;
131 while (i--)
132 asm volatile ("nop\n");
135 /* TODO: should be in target include file */
136 /*****************************************************************************
137 Definitions specific to Mini2440
138 *****************************************************************************/
140 #define SD_CD (1<<8) /* Port G */
141 #define SD_WP (1<<8) /* Port H */
143 /*****************************************************************************
144 Functions specific to S3C2440 SoC
145 *****************************************************************************/
147 #ifdef SD_DEBUG
148 static unsigned reg_copy[16], reg_copy2[16];
149 static void get_regs (unsigned *regs)
151 unsigned j;
152 volatile unsigned long *sdi_reg = &SDICON;
154 for (j=0; j < 16;j++)
156 *regs++ = *sdi_reg++;
160 static void dump_regs (unsigned *regs1, unsigned *regs2)
162 unsigned j;
163 volatile unsigned long*sdi_reg = &SDICON;
164 unsigned long diff;
166 for (j=0; j < 16;j++)
168 diff = *regs1 ^ *regs2;
169 if (diff)
170 dbgprintf ("%8x %8x %8x %8x\n", sdi_reg, *regs1, *regs2, diff );
171 regs1++;
172 regs2++;
173 sdi_reg++;
176 #endif
178 static void debug_r1(int cmd)
180 #if defined(SD_DEBUG)
181 dbgprintf("CMD%2.2d:SDICSTA=%04x [%c%c%c%c%c-%c%c%c%c%c%c%c] SDIRSP0=%08x [%d %s] \n",
182 cmd,
183 SDICSTA,
184 (SDICSTA & S3C2410_SDICMDSTAT_CRCFAIL) ? 'C' : ' ',
185 (SDICSTA & S3C2410_SDICMDSTAT_CMDSENT) ? 'S' : ' ',
186 (SDICSTA & S3C2410_SDICMDSTAT_CMDTIMEOUT) ? 'T' : ' ',
187 (SDICSTA & S3C2410_SDICMDSTAT_RSPFIN) ? 'R' : ' ',
188 (SDICSTA & S3C2410_SDICMDSTAT_XFERING) ? 'X' : ' ',
190 (SDICSTA & 0x40) ? 'P' : ' ',
191 (SDICSTA & 0x20) ? 'A' : ' ',
192 (SDICSTA & 0x10) ? 'E' : ' ',
193 (SDICSTA & 0x08) ? 'C' : ' ',
194 (SDICSTA & 0x04) ? 'I' : ' ',
195 (SDICSTA & 0x02) ? 'R' : ' ',
196 (SDICSTA & 0x01) ? 'Z' : ' ',
198 SDIRSP0,
199 SD_R1_CURRENT_STATE(SDIRSP0),
200 (SDIRSP0 & SD_R1_READY_FOR_DATA) ? "RDY " : " "
202 #else
203 (void)cmd;
204 #endif
207 void SDI (void)
209 int status = SDIDSTA;
210 #ifndef HAVE_MULTIDRIVE
211 const int curr_card = 0;
212 #endif
214 transfer_error[curr_card] = status
215 #if 0
216 & ( S3C2410_SDIDSTA_CRCFAIL | S3C2410_SDIDSTA_RXCRCFAIL |
217 S3C2410_SDIDSTA_DATATIMEOUT )
218 #endif
221 SDIDSTA |= S3C2410_SDIDSTA_CLEAR_BITS; /* needed to clear int */
223 dbgprintf ("SDI %x\n", transfer_error[curr_card]);
225 wakeup_signal(&transfer_completion_signal);
227 /* Ack the interrupt */
228 SRCPND = SDI_MASK;
229 INTPND = SDI_MASK;
232 #if 0
233 void dma_callback (void)
235 const int status = SDIDSTA;
237 transfer_error[0] = status & (S3C2410_SDIDSTA_CRCFAIL |
238 S3C2410_SDIDSTA_RXCRCFAIL |
239 S3C2410_SDIDSTA_DATATIMEOUT );
241 SDIDSTA |= S3C2410_SDIDSTA_CLEAR_BITS; /* needed to clear int */
243 dbgprintf ("dma_cb\n");
244 wakeup_signal(&transfer_completion_signal);
246 #endif
248 static void init_sdi_controller(const int card_no)
250 (void)card_no;
252 /*****************************************************************************/
253 #ifdef MINI2440
254 /* Specific to Mini2440 */
256 /* Enable pullups on SDCMD and SDDAT pins */
257 S3C2440_GPIO_PULLUP (GPEUP, 6, GPIO_PULLUP_ENABLE);
258 S3C2440_GPIO_PULLUP (GPEUP, 7, GPIO_PULLUP_ENABLE);
259 S3C2440_GPIO_PULLUP (GPEUP, 8, GPIO_PULLUP_ENABLE);
260 S3C2440_GPIO_PULLUP (GPEUP, 9, GPIO_PULLUP_ENABLE);
261 S3C2440_GPIO_PULLUP (GPEUP, 10, GPIO_PULLUP_ENABLE);
263 /* Enable special function for SDCMD, SDCLK and SDDAT pins */
264 S3C2440_GPIO_CONFIG (GPECON, 5, GPIO_FUNCTION);
265 S3C2440_GPIO_CONFIG (GPECON, 6, GPIO_FUNCTION);
266 S3C2440_GPIO_CONFIG (GPECON, 7, GPIO_FUNCTION);
267 S3C2440_GPIO_CONFIG (GPECON, 8, GPIO_FUNCTION);
268 S3C2440_GPIO_CONFIG (GPECON, 9, GPIO_FUNCTION);
269 S3C2440_GPIO_CONFIG (GPECON, 10, GPIO_FUNCTION);
271 /* Card Detect input */
272 S3C2440_GPIO_CONFIG (GPGCON, 8, GPIO_INPUT);
273 /* enable external irq 8-23 on the internal interrupt controller */
274 INTMSK &= ~1<<5;
275 /* enable GPG8 IRQ on the external interrupt controller */
276 EINTMASK &= ~(1<<16);
279 /* Write Protect input */
280 S3C2440_GPIO_CONFIG (GPHCON, 8, GPIO_INPUT);
281 /*****************************************************************************/
282 #else
283 #error Unsupported target
284 #endif
285 /*****************************************************************************/
287 /* About 400KHz for initial comms with card */
288 SDIPRE = PCLK / INITIAL_CLK - 1;
289 /* Byte order=Type A (Little Endian), clock enable */
290 SDICON = S3C2410_SDICON_CLOCKTYPE;
291 SDIFSTA |= S3C2440_SDIFSTA_FIFORESET;
292 SDIBSIZE = SD_BLOCK_SIZE;
293 SDIDTIMER= 0x7fffff; /* Set timeout count - max value */
295 /* Enable interupt on Data Finish or data transfer error */
296 /* Clear pending source */
297 SRCPND = SDI_MASK;
298 INTPND = SDI_MASK;
300 #if 1
301 /* Enable interrupt in controller */
302 s3c_regclr32(&INTMOD, SDI_MASK);
303 s3c_regclr32(&INTMSK, SDI_MASK);
305 SDIIMSK |= S3C2410_SDIIMSK_DATAFINISH
306 | S3C2410_SDIIMSK_DATATIMEOUT
307 | S3C2410_SDIIMSK_DATACRC
308 | S3C2410_SDIIMSK_CRCSTATUS
309 | S3C2410_SDIIMSK_FIFOFAIL
311 #endif
314 static bool send_cmd(const int card_no, const int cmd, const int arg,
315 const int flags, long *response)
317 bool ret;
318 unsigned val, status;
319 (void)card_no;
321 #ifdef SD_DEBUG
322 get_regs (reg_copy);
323 #endif
324 /* A major bodge. For some reason a delay is required here */
325 mci_delay();
326 dbgprintf ("send_cmd: c=%3.3d a=%08x f=%02x \n", cmd, arg, flags);
328 #ifdef SD_DEBUG
329 get_regs (reg_copy2);
330 dump_regs (reg_copy, reg_copy2);
331 #endif
333 #if 0
334 while (SDICSTA & S3C2410_SDICMDSTAT_XFERING)
335 ; /* wait ?? */
336 #endif
337 /* set up new command */
339 if (flags & MCI_ARG)
340 SDICARG = arg;
341 else
342 SDICARG = 0;
344 val = cmd | S3C2410_SDICMDCON_CMDSTART | S3C2410_SDICMDCON_SENDERHOST;
345 if(flags & MCI_RESP)
347 val |= S3C2410_SDICMDCON_WAITRSP;
348 if(flags & MCI_LONG_RESP)
349 val |= S3C2410_SDICMDCON_LONGRSP;
352 /* Clear command/data status flags */
353 SDICSTA |= 0x0f << 9;
354 SDIDSTA |= S3C2410_SDIDSTA_CLEAR_BITS;
356 /* Initiate the command */
357 SDICCON = val;
359 if (flags & MCI_RESP)
361 /* wait for response or timeout */
364 status = SDICSTA;
365 } while ( (status & (S3C2410_SDICMDSTAT_RSPFIN |
366 S3C2410_SDICMDSTAT_CMDTIMEOUT) ) == 0);
367 debug_r1(cmd);
368 if (status & S3C2410_SDICMDSTAT_CMDTIMEOUT)
369 ret = false;
370 else if (status & (S3C2410_SDICMDSTAT_RSPFIN))
372 /* resp received */
373 if(flags & MCI_LONG_RESP)
375 /* store the response in reverse word order */
376 response[0] = SDIRSP3;
377 response[1] = SDIRSP2;
378 response[2] = SDIRSP1;
379 response[3] = SDIRSP0;
381 else
382 response[0] = SDIRSP0;
383 ret = true;
385 else
386 ret = true;
388 else
390 /* wait for command completion or timeout */
393 status = SDICSTA;
394 } while ( (status & (S3C2410_SDICMDSTAT_CMDSENT |
395 S3C2410_SDICMDSTAT_CMDTIMEOUT)) == 0);
396 debug_r1(cmd);
397 if (status & S3C2410_SDICMDSTAT_CMDTIMEOUT)
398 ret = false;
399 else
400 ret = true;
403 /* Clear Command status flags */
404 SDICSTA |= 0x0f << 9;
406 mci_delay();
408 return ret;
411 static int sd_init_card(const int card_no)
413 unsigned long temp_reg[4];
414 unsigned long response;
415 long init_timeout;
416 bool sdhc;
417 int i;
419 if(!send_cmd(card_no, SD_GO_IDLE_STATE, 0, MCI_NO_FLAGS, NULL))
420 return -1;
422 mci_delay();
424 sdhc = false;
425 if(send_cmd(card_no, SD_SEND_IF_COND, 0x1AA, MCI_RESP|MCI_ARG, &response))
426 if((response & 0xFFF) == 0x1AA)
427 sdhc = true;
429 /* timeout for initialization is 1sec, from SD Specification 2.00 */
430 init_timeout = current_tick + HZ;
432 do {
433 /* timeout */
434 if(current_tick > init_timeout)
435 return -2;
437 /* app_cmd */
438 if( !send_cmd(card_no, SD_APP_CMD, 0, MCI_RESP|MCI_ARG, &response) ||
439 !(response & (1<<5)) )
441 return -3;
444 /* acmd41 */
445 if(!send_cmd(card_no, SD_APP_OP_COND, (sdhc ? 0x40FF8000 : (1<<23)),
446 MCI_RESP|MCI_ARG, &card_info[card_no].ocr))
448 return -4;
451 } while(!(card_info[card_no].ocr & (1<<31)));
453 /* send CID */
454 if(!send_cmd(card_no, SD_ALL_SEND_CID, 0, MCI_RESP|MCI_LONG_RESP|MCI_ARG,
455 temp_reg))
456 return -5;
458 for(i=0; i<4; i++)
459 card_info[card_no].cid[3-i] = temp_reg[i];
461 /* send RCA */
462 if(!send_cmd(card_no, SD_SEND_RELATIVE_ADDR, 0, MCI_RESP|MCI_ARG,
463 &card_info[card_no].rca))
464 return -6;
466 /* send CSD */
467 if(!send_cmd(card_no, SD_SEND_CSD, card_info[card_no].rca,
468 MCI_RESP|MCI_LONG_RESP|MCI_ARG, temp_reg))
469 return -7;
471 for(i=0; i<4; i++)
472 card_info[card_no].csd[3-i] = temp_reg[i];
474 sd_parse_csd(&card_info[card_no]);
476 if(!send_cmd(card_no, SD_SELECT_CARD, card_info[card_no].rca, MCI_ARG, NULL))
477 return -9;
479 if(!send_cmd(card_no, SD_APP_CMD, card_info[card_no].rca, MCI_ARG, NULL))
480 return -10;
482 if(!send_cmd(card_no, SD_SET_BUS_WIDTH, card_info[card_no].rca | 2, MCI_ARG, NULL))
483 return -11;
485 if(!send_cmd(card_no, SD_SET_BLOCKLEN, card_info[card_no].blocksize, MCI_ARG,
486 NULL))
487 return -12;
489 card_info[card_no].initialized = 1;
491 /* full speed for controller clock */
492 SDIPRE = PCLK / SD_CLK - 1;
493 mci_delay();
495 return EC_OK;
498 /*****************************************************************************
499 Generic functions
500 *****************************************************************************/
502 static inline bool card_detect_target(void)
504 /* TODO - use interrupt on change? */
505 #ifdef MINI2440
506 return (GPGDAT & SD_CD) == 0;
507 #else
508 #error Unsupported target
509 #endif
513 /*****************************************************************************/
514 #ifdef HAVE_HOTSWAP
516 static int sd1_oneshot_callback(struct timeout *tmo)
518 (void)tmo;
520 /* This is called only if the state was stable for 300ms - check state
521 * and post appropriate event. */
522 if (card_detect_target())
524 queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
526 else
527 queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
528 return 0;
531 void EINT8_23(void)
533 static struct timeout sd1_oneshot;
534 EINTPEND = (1<<16); /* ack irq on external, then internal irq controller */
535 SRCPND = (1<<5);
536 INTPND = (1<<5);
537 /* add task to inform the system about the SD insertion
538 * sanity check if it's still inserted after 300ms */
539 timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0);
542 bool sd_removable(IF_MD_NONVOID(int card_no))
544 #ifndef HAVE_MULTIDRIVE
545 const int card_no = 0;
546 #endif
547 dbgprintf ("sd_remov (hs) [%d] %d\n", card_no, card_no == CARD_NUM_SLOT );
548 return (card_no == CARD_NUM_SLOT);
551 bool sd_present(IF_MD_NONVOID(int card_no))
553 #ifdef HAVE_MULTIDRIVE
554 (void)card_no;
555 #endif
556 dbgprintf ("sd_pres (hs) [%d] %d\n", card_no, card_detect_target());
557 return card_detect_target();
560 /*****************************************************************************/
561 #else
563 bool sd_removable(IF_MD_NONVOID(int card_no))
565 #ifndef HAVE_MULTIDRIVE
566 const int card_no = 0;
567 #endif
568 (void)card_no;
570 /* not applicable */
571 dbgprintf ("sd_remov");
572 return false;
575 #endif /* HAVE_HOTSWAP */
576 /*****************************************************************************/
578 static void sd_thread(void) __attribute__((noreturn));
579 static void sd_thread(void)
581 struct queue_event ev;
583 /* TODO */
584 while (1)
586 queue_wait_w_tmo(&sd_queue, &ev, HZ);
587 switch ( ev.id )
589 #ifdef HAVE_HOTSWAP
590 case SYS_HOTSWAP_INSERTED:
591 case SYS_HOTSWAP_EXTRACTED:
593 int success = 1;
594 fat_lock(); /* lock-out FAT activity first -
595 prevent deadlocking via disk_mount that
596 would cause a reverse-order attempt with
597 another thread */
598 mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
599 into driver that bypass the fat cache */
601 /* We now have exclusive control of fat cache and ata */
603 disk_unmount(0); /* release "by force", ensure file
604 descriptors aren't leaked and any busy
605 ones are invalid if mounting */
607 /* Force card init for new card, re-init for re-inserted one or
608 * clear if the last attempt to init failed with an error. */
609 card_info[0].initialized = 0;
611 if (ev.id == SYS_HOTSWAP_INSERTED)
613 /* FIXME: once sd_enabled is implement properly,
614 * reinitializing the controllers might be needed */
615 sd_enable(true);
616 if (success < 0) /* initialisation failed */
617 panicf("SD init failed : %d", success);
618 success = disk_mount(0); /* 0 if fail */
621 /* notify the system about the changed filesystems
623 if (success)
624 queue_broadcast(SYS_FS_CHANGED, 0);
626 /* Access is now safe */
627 mutex_unlock(&sd_mtx);
628 fat_unlock();
629 sd_enable(false);
631 break;
632 #endif
637 static int sd_wait_for_state(const int card_no, unsigned int state)
639 unsigned long response = 0;
640 unsigned int timeout = HZ; /* ticks */
641 long t = current_tick;
643 while (1)
645 long tick;
647 if(!send_cmd(card_no, SD_SEND_STATUS, card_info[card_no].rca,
648 MCI_RESP|MCI_ARG, &response))
649 return -1;
651 if( (SD_R1_CURRENT_STATE(response) == state) )
652 return 0;
654 if(TIME_AFTER(current_tick, t + timeout))
655 return -2;
657 if (TIME_AFTER((tick = current_tick), next_yield))
659 yield();
660 timeout += current_tick - tick;
661 next_yield = tick + MIN_YIELD_PERIOD;
666 static int sd_transfer_sectors(int card_no, unsigned long start,
667 int count, void* buf, const bool write)
669 int ret = EC_OK;
670 unsigned loops = 0;
671 struct dma_request request;
673 mutex_lock(&sd_mtx);
674 sd_enable(true);
675 set_leds(SD_ACTIVE_LED);
677 #ifdef HAVE_MULTIDRIVE
678 curr_card = card_no;
679 #endif
680 if (card_info[card_no].initialized <= 0)
682 ret = sd_init_card(card_no);
683 if (!(card_info[card_no].initialized))
684 goto sd_transfer_error;
687 last_disk_activity = current_tick;
689 ret = sd_wait_for_state(card_no, SD_TRAN);
690 if (ret < 0)
692 ret -= 20;
693 goto sd_transfer_error;
696 dma_retain();
698 while(count)
700 /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH
701 * register, so we have to transfer maximum 127 sectors at a time. */
702 unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */
703 void *dma_buf;
704 const int cmd =
705 write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK;
706 unsigned long start_addr = start;
708 dma_buf = aligned_buffer;
709 if(transfer > UNALIGNED_NUM_SECTORS)
710 transfer = UNALIGNED_NUM_SECTORS;
711 if(write)
712 memcpy(uncached_buffer, buf, transfer * SD_BLOCK_SIZE);
714 /* Set start_addr to the correct unit (blocks or bytes) */
715 if(!(card_info[card_no].ocr & SD_OCR_CARD_CAPACITY_STATUS))/* not SDHC */
716 start_addr *= SD_BLOCK_SIZE;
718 /* TODO? */
719 SDIFSTA = SDIFSTA | S3C2440_SDIFSTA_FIFORESET;
720 SDIDCON = S3C2440_SDIDCON_DS_WORD |
721 S3C2410_SDIDCON_BLOCKMODE | S3C2410_SDIDCON_WIDEBUS |
722 S3C2410_SDIDCON_DMAEN |
723 S3C2440_SDIDCON_DATSTART |
724 ( transfer << 0);
725 if (write)
726 SDIDCON |= S3C2410_SDIDCON_TXAFTERRESP | S3C2410_SDIDCON_XFER_TXSTART;
727 else
728 SDIDCON |= S3C2410_SDIDCON_RXAFTERCMD | S3C2410_SDIDCON_XFER_RXSTART;
730 SDIDSTA |= S3C2410_SDIDSTA_CLEAR_BITS; /* needed to clear int */
731 SRCPND = SDI_MASK;
732 INTPND = SDI_MASK;
734 /* Initiate read/write command */
735 if(!send_cmd(card_no, cmd, start_addr, MCI_ARG | MCI_RESP, NULL))
737 ret -= 3*20;
738 goto sd_transfer_error;
741 if(write)
743 request.source_addr = dma_buf;
744 request.source_control = DISRCC_LOC_AHB | DISRCC_INC_AUTO;
745 request.dest_addr = &SDIDAT_LLE;
746 request.dest_control = DISRCC_LOC_APB | DISRCC_INC_FIXED;
747 request.count = transfer * SD_BLOCK_SIZE / sizeof(long);
748 request.source_map = DMA_SRC_MAP_SDI;
749 request.control = DCON_DMD_HS | DCON_SYNC_APB |
750 DCON_HW_SEL |
751 DCON_NO_RELOAD | DCON_DSZ_WORD;
752 request.callback = NULL;
754 dma_enable_channel(0, &request);
756 else
758 request.source_addr = &SDIDAT_LLE;
759 request.source_control = DISRCC_LOC_APB | DISRCC_INC_FIXED;
760 request.dest_addr = dma_buf;
761 request.dest_control = DISRCC_LOC_AHB | DISRCC_INC_AUTO;
762 request.count = transfer * SD_BLOCK_SIZE / sizeof(long);
763 request.source_map = DMA_SRC_MAP_SDI;
764 request.control = DCON_DMD_HS | DCON_SYNC_APB |
765 DCON_HW_SEL |
766 DCON_NO_RELOAD | DCON_DSZ_WORD;
767 request.callback = NULL;
769 dma_enable_channel(0, &request);
772 #if 0
773 /* FIXME : we should check if the timeouts calculated from the card's
774 * CSD are lower, and use them if it is the case
775 * Note : the OF doesn't seem to use them anyway */
776 MCI_DATA_TIMER(drive) = write ?
777 SD_MAX_WRITE_TIMEOUT : SD_MAX_READ_TIMEOUT;
778 MCI_DATA_LENGTH(drive) = transfer * card_info[drive].blocksize;
779 MCI_DATA_CTRL(drive) = (1<<0) /* enable */ |
780 (!write<<1) /* transfer direction */ |
781 (1<<3) /* DMA */ |
782 (9<<4) /* 2^9 = 512 */ ;
783 #endif
785 wakeup_wait(&transfer_completion_signal, 100 /*TIMEOUT_BLOCK*/);
787 /* wait for DMA to finish */
788 while (DSTAT0 & DSTAT_STAT_BUSY)
791 #if 0
792 status = SDIDSTA;
793 while ((status & (S3C2410_SDIDSTA_DATATIMEOUT|S3C2410_SDIDSTA_XFERFINISH)) == 0)
795 status = SDIDSTA;
797 dbgprintf("%x \n", status);
798 #endif
799 if( transfer_error[card_no] & S3C2410_SDIDSTA_XFERFINISH )
801 if(!write)
802 memcpy(buf, uncached_buffer, transfer * SD_BLOCK_SIZE);
803 buf += transfer * SD_BLOCK_SIZE;
804 start += transfer;
805 count -= transfer;
806 loops = 0; /* reset errors counter */
808 else
810 dbgprintf ("SD transfer error : 0x%x\n", transfer_error[card_no]);
812 if(loops++ > MAX_TRANSFER_ERRORS)
814 led_flash(LED1|LED2, LED3|LED4);
815 /* panicf("SD transfer error : 0x%x", transfer_error[card_no]); */
819 last_disk_activity = current_tick;
821 if(!send_cmd(card_no, SD_STOP_TRANSMISSION, 0, MCI_RESP, NULL))
823 ret = -4*20;
824 goto sd_transfer_error;
827 #if 0
828 ret = sd_wait_for_state(card_no, SD_TRAN);
829 if (ret < 0)
831 ret -= 5*20;
832 goto sd_transfer_error;
834 #endif
837 ret = EC_OK;
839 sd_transfer_error:
841 dma_release();
843 clear_leds(SD_ACTIVE_LED);
844 sd_enable(false);
846 if (ret) /* error */
847 card_info[card_no].initialized = 0;
849 mutex_unlock(&sd_mtx);
850 return ret;
853 int sd_read_sectors(IF_MD2(int card_no,) unsigned long start, int incount,
854 void* inbuf)
856 int ret;
858 #ifdef HAVE_MULTIDRIVE
859 dbgprintf ("sd_read %d %x %d\n", card_no, start, incount);
860 #else
861 dbgprintf ("sd_read %x %d\n", start, incount);
862 #endif
863 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
864 if (!card_detect_target())
865 ret = 0; /* assume success */
866 else
867 #endif
868 ret = sd_transfer_sectors(card_no, start, incount, inbuf, false);
869 dbgprintf ("sd_read, ret=%d\n", ret);
870 return ret;
873 /*****************************************************************************/
874 int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
875 const void* outbuf)
877 #ifdef BOOTLOADER /* we don't need write support in bootloader */
878 #ifdef HAVE_MULTIDRIVE
879 (void) drive;
880 #endif
881 (void) start;
882 (void) count;
883 (void) outbuf;
884 return -1;
885 #else
886 #ifdef HAVE_MULTIDRIVE
887 dbgprintf ("sd_write %d %x %d\n", drive, start, count);
888 #else
889 dbgprintf ("sd_write %x %d\n", start, count);
890 #endif
891 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
892 if (!card_detect_target())
893 return 0; /* assume success */
894 else
895 #endif
896 return sd_transfer_sectors(drive, start, count, (void*)outbuf, true);
897 #endif
899 /*****************************************************************************/
901 void sd_enable(bool on)
903 dbgprintf ("sd_enable %d\n", on);
904 /* TODO: enable/disable SDI clock */
906 if (sd_enabled == on)
907 return; /* nothing to do */
908 if (on)
910 sd_enabled = true;
912 else
914 sd_enabled = false;
918 int sd_init(void)
920 int ret = EC_OK;
921 dbgprintf ("\n==============================\n");
922 dbgprintf (" sd_init\n");
923 dbgprintf ("==============================\n");
925 init_sdi_controller (0);
926 #ifndef BOOTLOADER
927 sd_enabled = true;
928 sd_enable(false);
929 #endif
930 wakeup_init(&transfer_completion_signal);
931 /* init mutex */
932 mutex_init(&sd_mtx);
933 queue_init(&sd_queue, true);
934 create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
935 sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
937 uncached_buffer = UNCACHED_ADDR(&aligned_buffer[0]);
939 #ifdef HAVE_HOTSWAP
941 * prepare detecting of SD insertion (not extraction) */
942 unsigned long for_extint = EXTINT2;
943 unsigned long for_gpgcon = GPGCON;
944 for_extint &= ~0x7;
945 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
946 for_extint |= 0x2; /* detect falling edge only (0 means SD inserted) */
947 #else
948 for_extint |= 0x3; /* detect both, raising and falling, edges */
949 #endif
950 for_gpgcon &= ~(0x3<<16);
951 for_gpgcon |= (0x2<<16); /* enable interrupt on pin 8 */
952 EXTINT2 = for_extint;
953 GPGCON = for_gpgcon;
954 #endif
956 initialized = true;
957 return ret;
960 long sd_last_disk_activity(void)
962 return last_disk_activity;
965 tCardInfo *card_get_info_target(int card_no)
967 return &card_info[card_no];
970 /*****************************************************************************/
971 #ifdef CONFIG_STORAGE_MULTI
973 int sd_num_drives(int first_drive)
975 dbgprintf ("sd_num_drv");
976 #if 0
977 /* Store which logical drive number(s) we have been assigned */
978 sd_first_drive = first_drive;
979 #endif
981 return NUM_CARDS;
984 void sd_sleepnow(void)
988 bool sd_disk_is_active(void)
990 return false;
993 int sd_soft_reset(void)
995 return 0;
998 int sd_spinup_time(void)
1000 return 0;
1003 #endif /* CONFIG_STORAGE_MULTI */
1004 /*****************************************************************************/