diff options
author | Thomas Martitz <kugel@rockbox.org> | 2009-11-25 23:23:21 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2009-11-25 23:23:21 +0000 |
commit | 10753f195bb14413e179ae3091b633c636973760 (patch) | |
tree | ca969778ba6d322bc8416c9055cafbb3a6bad660 | |
parent | f2f5b7c85107e2108f9bd0fa4aef63c84057917f (diff) | |
download | rockbox-10753f195bb14413e179ae3091b633c636973760.tar.gz rockbox-10753f195bb14413e179ae3091b633c636973760.zip |
Mini2440: Cleanup SD driver a bit, undefine SD_DEBUG for faster transfers, implement hotswap and HAVE_HOTSWAP_STORAGE_AS_MAIN.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23754 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/export/config-mini2440.h | 6 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/sd-s3c2440.c | 162 |
2 files changed, 133 insertions, 35 deletions
diff --git a/firmware/export/config-mini2440.h b/firmware/export/config-mini2440.h index 739489becd..5dad250930 100644 --- a/firmware/export/config-mini2440.h +++ b/firmware/export/config-mini2440.h | |||
@@ -39,11 +39,11 @@ | |||
39 | /* define the storage type */ | 39 | /* define the storage type */ |
40 | #define CONFIG_STORAGE STORAGE_SD | 40 | #define CONFIG_STORAGE STORAGE_SD |
41 | 41 | ||
42 | /* | ||
43 | #define HAVE_MULTIDRIVE | 42 | #define HAVE_MULTIDRIVE |
44 | #define NUM_DRIVES 2 | 43 | #define NUM_DRIVES 1 // no access to NAND yet |
45 | #define HAVE_HOTSWAP | 44 | #define HAVE_HOTSWAP |
46 | */ | 45 | #define HAVE_HOTSWAP_STORAGE_AS_MAIN |
46 | #define INCLUDE_TIMEOUT_API | ||
47 | 47 | ||
48 | /* Disk storage */ | 48 | /* Disk storage */ |
49 | /* define this if you have a disk storage, i.e. something | 49 | /* define this if you have a disk storage, i.e. something |
diff --git a/firmware/target/arm/s3c2440/sd-s3c2440.c b/firmware/target/arm/s3c2440/sd-s3c2440.c index 3117efda1f..6213cbd003 100644 --- a/firmware/target/arm/s3c2440/sd-s3c2440.c +++ b/firmware/target/arm/s3c2440/sd-s3c2440.c | |||
@@ -19,18 +19,22 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #define SD_DEBUG | 22 | //#define SD_DEBUG |
23 | 23 | ||
24 | #include "sd.h" | 24 | #include "sd.h" |
25 | #include "system.h" | 25 | #include "system.h" |
26 | #include <string.h> | 26 | #include <string.h> |
27 | #include "hotswap.h" | ||
28 | #include "thread.h" | 27 | #include "thread.h" |
29 | #include "panic.h" | 28 | #include "panic.h" |
30 | 29 | ||
31 | #ifdef SD_DEBUG | 30 | #ifdef SD_DEBUG |
32 | #include "uart-s3c2440.h" | 31 | #include "uart-s3c2440.h" |
33 | #endif | 32 | #endif |
33 | #ifdef HAVE_HOTSWAP | ||
34 | #include "hotswap.h" | ||
35 | #include "disk.h" | ||
36 | #include "fat.h" | ||
37 | #endif | ||
34 | #include "dma-target.h" | 38 | #include "dma-target.h" |
35 | #include "system-target.h" | 39 | #include "system-target.h" |
36 | #include "led-mini2440.h" | 40 | #include "led-mini2440.h" |
@@ -121,6 +125,12 @@ static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS * SD_BLOCK_SIZE] | |||
121 | __attribute__((aligned(32))); | 125 | __attribute__((aligned(32))); |
122 | static unsigned char * uncached_buffer; | 126 | static unsigned char * uncached_buffer; |
123 | 127 | ||
128 | static inline void mci_delay(void) | ||
129 | { | ||
130 | int i = 0xffff; | ||
131 | while (i--) | ||
132 | asm volatile ("nop\n"); | ||
133 | } | ||
124 | 134 | ||
125 | /* TODO: should be in target include file */ | 135 | /* TODO: should be in target include file */ |
126 | /***************************************************************************** | 136 | /***************************************************************************** |
@@ -133,12 +143,6 @@ static unsigned char * uncached_buffer; | |||
133 | /***************************************************************************** | 143 | /***************************************************************************** |
134 | Functions specific to S3C2440 SoC | 144 | Functions specific to S3C2440 SoC |
135 | *****************************************************************************/ | 145 | *****************************************************************************/ |
136 | static inline void mci_delay(void) | ||
137 | { | ||
138 | /* Does this get optimised out ? */ | ||
139 | int i = 0xffff; | ||
140 | while(i--) ; | ||
141 | } | ||
142 | 146 | ||
143 | #ifdef SD_DEBUG | 147 | #ifdef SD_DEBUG |
144 | static unsigned reg_copy[16], reg_copy2[16]; | 148 | static unsigned reg_copy[16], reg_copy2[16]; |
@@ -163,7 +167,7 @@ static void dump_regs (unsigned *regs1, unsigned *regs2) | |||
163 | { | 167 | { |
164 | diff = *regs1 ^ *regs2; | 168 | diff = *regs1 ^ *regs2; |
165 | if (diff) | 169 | if (diff) |
166 | uart_printf ("%8x %8x %8x %8x\n", sdi_reg, *regs1, *regs2, diff ); | 170 | dbgprintf ("%8x %8x %8x %8x\n", sdi_reg, *regs1, *regs2, diff ); |
167 | regs1++; | 171 | regs1++; |
168 | regs2++; | 172 | regs2++; |
169 | sdi_reg++; | 173 | sdi_reg++; |
@@ -174,7 +178,7 @@ static void dump_regs (unsigned *regs1, unsigned *regs2) | |||
174 | static void debug_r1(int cmd) | 178 | static void debug_r1(int cmd) |
175 | { | 179 | { |
176 | #if defined(SD_DEBUG) | 180 | #if defined(SD_DEBUG) |
177 | uart_printf("CMD%2.2d:SDICSTA=%04x [%c%c%c%c%c-%c%c%c%c%c%c%c] SDIRSP0=%08x [%d %s] \n", | 181 | dbgprintf("CMD%2.2d:SDICSTA=%04x [%c%c%c%c%c-%c%c%c%c%c%c%c] SDIRSP0=%08x [%d %s] \n", |
178 | cmd, | 182 | cmd, |
179 | SDICSTA, | 183 | SDICSTA, |
180 | (SDICSTA & S3C2410_SDICMDSTAT_CRCFAIL) ? 'C' : ' ', | 184 | (SDICSTA & S3C2410_SDICMDSTAT_CRCFAIL) ? 'C' : ' ', |
@@ -493,10 +497,25 @@ static int sd_init_card(const int card_no) | |||
493 | /*****************************************************************************/ | 497 | /*****************************************************************************/ |
494 | #ifdef HAVE_HOTSWAP | 498 | #ifdef HAVE_HOTSWAP |
495 | 499 | ||
500 | static int sd1_oneshot_callback(struct timeout *tmo) | ||
501 | { | ||
502 | (void)tmo; | ||
503 | |||
504 | /* This is called only if the state was stable for 300ms - check state | ||
505 | * and post appropriate event. */ | ||
506 | if (card_detect_target()) | ||
507 | { | ||
508 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | ||
509 | } | ||
510 | else | ||
511 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
512 | return 0; | ||
513 | } | ||
514 | |||
496 | bool card_detect_target(void) | 515 | bool card_detect_target(void) |
497 | { | 516 | { |
498 | /* TODO - use interrupt on change? */ | 517 | /* TODO - use interrupt on change? */ |
499 | #ifdef MINI2440 | 518 | #ifdef MINI2440 |
500 | return (GPGDAT & SD_CD) == 0; | 519 | return (GPGDAT & SD_CD) == 0; |
501 | #else | 520 | #else |
502 | #error Unsupported target | 521 | #error Unsupported target |
@@ -505,18 +524,30 @@ bool card_detect_target(void) | |||
505 | 524 | ||
506 | void card_enable_monitoring_target(bool on) | 525 | void card_enable_monitoring_target(bool on) |
507 | { | 526 | { |
508 | (void)on; | 527 | if (on) |
509 | /* TODO */ | 528 | { /* enable external irq 8-23 on the internal interrupt controller */ |
529 | INTMSK &= ~1<<5; | ||
530 | /* enable GPG8 IRQ on the external interrupt controller */ | ||
531 | EINTMASK &= ~(1<<16); | ||
532 | } | ||
533 | else | ||
534 | { | ||
535 | /* mask internal and external IRQs */ | ||
536 | INTMSK |= 1<<5; | ||
537 | EINTMASK |= (1<<16); | ||
538 | } | ||
510 | } | 539 | } |
511 | 540 | ||
512 | #if 0 | 541 | void EINT8_23(void) |
513 | void EXT0(void) | ||
514 | { | 542 | { |
515 | static struct timeout sd1_oneshot; | 543 | static struct timeout sd1_oneshot; |
516 | 544 | EINTPEND = (1<<16); /* ack irq on external, then internal irq controller */ | |
517 | /* TODO */ | 545 | SRCPND = (1<<5); |
546 | INTPND = (1<<5); | ||
547 | /* add task to inform the system about the SD insertion | ||
548 | * sanity check if it's still inserted after 300ms */ | ||
549 | timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0); | ||
518 | } | 550 | } |
519 | #endif | ||
520 | 551 | ||
521 | bool sd_removable(IF_MD_NONVOID(int card_no)) | 552 | bool sd_removable(IF_MD_NONVOID(int card_no)) |
522 | { | 553 | { |
@@ -569,9 +600,52 @@ static void sd_thread(void) | |||
569 | while (1) | 600 | while (1) |
570 | { | 601 | { |
571 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | 602 | queue_wait_w_tmo(&sd_queue, &ev, HZ); |
572 | |||
573 | switch ( ev.id ) | 603 | switch ( ev.id ) |
574 | { | 604 | { |
605 | #ifdef HAVE_HOTSWAP | ||
606 | case SYS_HOTSWAP_INSERTED: | ||
607 | case SYS_HOTSWAP_EXTRACTED: | ||
608 | { | ||
609 | int success = 1; | ||
610 | fat_lock(); /* lock-out FAT activity first - | ||
611 | prevent deadlocking via disk_mount that | ||
612 | would cause a reverse-order attempt with | ||
613 | another thread */ | ||
614 | mutex_lock(&sd_mtx); /* lock-out card activity - direct calls | ||
615 | into driver that bypass the fat cache */ | ||
616 | |||
617 | /* We now have exclusive control of fat cache and ata */ | ||
618 | |||
619 | disk_unmount(0); /* release "by force", ensure file | ||
620 | descriptors aren't leaked and any busy | ||
621 | ones are invalid if mounting */ | ||
622 | |||
623 | /* Force card init for new card, re-init for re-inserted one or | ||
624 | * clear if the last attempt to init failed with an error. */ | ||
625 | card_info[0].initialized = 0; | ||
626 | |||
627 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
628 | { | ||
629 | /* FIXME: once sd_enabled is implement properly, | ||
630 | * reinitializing the controllers might be needed */ | ||
631 | sd_enable(true); | ||
632 | if (success < 0) /* initialisation failed */ | ||
633 | panicf("SD init failed : %d", success); | ||
634 | success = disk_mount(0); /* 0 if fail */ | ||
635 | } | ||
636 | |||
637 | /* notify the system about the changed filesystems | ||
638 | */ | ||
639 | if (success) | ||
640 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
641 | |||
642 | /* Access is now safe */ | ||
643 | mutex_unlock(&sd_mtx); | ||
644 | fat_unlock(); | ||
645 | sd_enable(false); | ||
646 | } | ||
647 | break; | ||
648 | #endif | ||
575 | } | 649 | } |
576 | } | 650 | } |
577 | } | 651 | } |
@@ -605,12 +679,9 @@ static int sd_wait_for_state(const int card_no, unsigned int state) | |||
605 | } | 679 | } |
606 | } | 680 | } |
607 | 681 | ||
608 | static int sd_transfer_sectors(IF_MD2(int card_no,) unsigned long start, | 682 | static int sd_transfer_sectors(int card_no, unsigned long start, |
609 | int count, void* buf, const bool write) | 683 | int count, void* buf, const bool write) |
610 | { | 684 | { |
611 | #ifndef HAVE_MULTIDRIVE | ||
612 | const int card_no = 0; | ||
613 | #endif | ||
614 | int ret = EC_OK; | 685 | int ret = EC_OK; |
615 | unsigned loops = 0; | 686 | unsigned loops = 0; |
616 | struct dma_request request; | 687 | struct dma_request request; |
@@ -672,9 +743,9 @@ static int sd_transfer_sectors(IF_MD2(int card_no,) unsigned long start, | |||
672 | else | 743 | else |
673 | SDIDCON |= S3C2410_SDIDCON_RXAFTERCMD | S3C2410_SDIDCON_XFER_RXSTART; | 744 | SDIDCON |= S3C2410_SDIDCON_RXAFTERCMD | S3C2410_SDIDCON_XFER_RXSTART; |
674 | 745 | ||
675 | SDIDSTA |= S3C2410_SDIDSTA_CLEAR_BITS; /* needed to clear int */ | 746 | SDIDSTA |= S3C2410_SDIDSTA_CLEAR_BITS; /* needed to clear int */ |
676 | SRCPND = SDI_MASK; | 747 | SRCPND = SDI_MASK; |
677 | INTPND = SDI_MASK; | 748 | INTPND = SDI_MASK; |
678 | 749 | ||
679 | /* Initiate read/write command */ | 750 | /* Initiate read/write command */ |
680 | if(!send_cmd(card_no, cmd, start_addr, MCI_ARG | MCI_RESP, NULL)) | 751 | if(!send_cmd(card_no, cmd, start_addr, MCI_ARG | MCI_RESP, NULL)) |
@@ -739,7 +810,7 @@ static int sd_transfer_sectors(IF_MD2(int card_no,) unsigned long start, | |||
739 | { | 810 | { |
740 | status = SDIDSTA; | 811 | status = SDIDSTA; |
741 | } | 812 | } |
742 | uart_printf("%x \n", status); | 813 | dbgprintf("%x \n", status); |
743 | #endif | 814 | #endif |
744 | if( transfer_error[card_no] & S3C2410_SDIDSTA_XFERFINISH ) | 815 | if( transfer_error[card_no] & S3C2410_SDIDSTA_XFERFINISH ) |
745 | { | 816 | { |
@@ -805,7 +876,12 @@ int sd_read_sectors(IF_MD2(int card_no,) unsigned long start, int incount, | |||
805 | #else | 876 | #else |
806 | dbgprintf ("sd_read %x %d\n", start, incount); | 877 | dbgprintf ("sd_read %x %d\n", start, incount); |
807 | #endif | 878 | #endif |
808 | ret = sd_transfer_sectors(IF_MD2(card_no,) start, incount, inbuf, false); | 879 | #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN |
880 | if (!card_detect_target()) | ||
881 | ret = 0; /* assume success */ | ||
882 | else | ||
883 | #endif | ||
884 | ret = sd_transfer_sectors(card_no, start, incount, inbuf, false); | ||
809 | dbgprintf ("sd_read, ret=%d\n", ret); | 885 | dbgprintf ("sd_read, ret=%d\n", ret); |
810 | return ret; | 886 | return ret; |
811 | } | 887 | } |
@@ -827,9 +903,14 @@ int sd_write_sectors(IF_MD2(int card_no,) unsigned long start, int count, | |||
827 | dbgprintf ("sd_write %d %x %d\n", card_no, start, count); | 903 | dbgprintf ("sd_write %d %x %d\n", card_no, start, count); |
828 | #else | 904 | #else |
829 | dbgprintf ("sd_write %x %d\n", start, count); | 905 | dbgprintf ("sd_write %x %d\n", start, count); |
830 | #endif | 906 | #endif |
831 | return sd_transfer_sectors(IF_MD2(card_no,) start, count, (void*)outbuf, true); | 907 | #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN |
832 | #endif | 908 | if (!card_detect_target()) |
909 | return 0; /* assume success */ | ||
910 | else | ||
911 | #endif | ||
912 | return sd_transfer_sectors(card_no, start, count, (void*)outbuf, true); | ||
913 | #endif | ||
833 | } | 914 | } |
834 | /*****************************************************************************/ | 915 | /*****************************************************************************/ |
835 | 916 | ||
@@ -870,7 +951,24 @@ int sd_init(void) | |||
870 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | 951 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); |
871 | 952 | ||
872 | uncached_buffer = UNCACHED_ADDR(&aligned_buffer[0]); | 953 | uncached_buffer = UNCACHED_ADDR(&aligned_buffer[0]); |
873 | 954 | ||
955 | #ifdef HAVE_HOTSWAP | ||
956 | /* | ||
957 | * prepare detecting of SD insertion (not extraction) */ | ||
958 | unsigned long for_extint = EXTINT2; | ||
959 | unsigned long for_gpgcon = GPGCON; | ||
960 | for_extint &= ~0x7; | ||
961 | #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN | ||
962 | for_extint |= 0x2; /* detect falling edge only (0 means SD inserted) */ | ||
963 | #else | ||
964 | for_extint |= 0x3; /* detect both, raising and falling, edges */ | ||
965 | #endif | ||
966 | for_gpgcon &= ~(0x3<<16); | ||
967 | for_gpgcon |= (0x2<<16); /* enable interrupt on pin 8 */ | ||
968 | EXTINT2 = for_extint; | ||
969 | GPGCON = for_gpgcon; | ||
970 | #endif | ||
971 | |||
874 | initialized = true; | 972 | initialized = true; |
875 | return ret; | 973 | return ret; |
876 | } | 974 | } |