summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s3c2440
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2009-11-25 23:23:21 +0000
committerThomas Martitz <kugel@rockbox.org>2009-11-25 23:23:21 +0000
commit10753f195bb14413e179ae3091b633c636973760 (patch)
treeca969778ba6d322bc8416c9055cafbb3a6bad660 /firmware/target/arm/s3c2440
parentf2f5b7c85107e2108f9bd0fa4aef63c84057917f (diff)
downloadrockbox-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
Diffstat (limited to 'firmware/target/arm/s3c2440')
-rw-r--r--firmware/target/arm/s3c2440/sd-s3c2440.c162
1 files changed, 130 insertions, 32 deletions
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)));
122static unsigned char * uncached_buffer; 126static unsigned char * uncached_buffer;
123 127
128static 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 *****************************************************************************/
136static 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
144static unsigned reg_copy[16], reg_copy2[16]; 148static 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)
174static void debug_r1(int cmd) 178static 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
500static 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
496bool card_detect_target(void) 515bool 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
506void card_enable_monitoring_target(bool on) 525void 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 541void EINT8_23(void)
513void 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
521bool sd_removable(IF_MD_NONVOID(int card_no)) 552bool 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
608static int sd_transfer_sectors(IF_MD2(int card_no,) unsigned long start, 682static 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}