mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-09 05:05:20 -05:00
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
This commit is contained in:
parent
f2f5b7c851
commit
10753f195b
2 changed files with 133 additions and 35 deletions
|
|
@ -19,18 +19,22 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define SD_DEBUG
|
||||
//#define SD_DEBUG
|
||||
|
||||
#include "sd.h"
|
||||
#include "system.h"
|
||||
#include <string.h>
|
||||
#include "hotswap.h"
|
||||
#include "thread.h"
|
||||
#include "panic.h"
|
||||
|
||||
#ifdef SD_DEBUG
|
||||
#include "uart-s3c2440.h"
|
||||
#endif
|
||||
#ifdef HAVE_HOTSWAP
|
||||
#include "hotswap.h"
|
||||
#include "disk.h"
|
||||
#include "fat.h"
|
||||
#endif
|
||||
#include "dma-target.h"
|
||||
#include "system-target.h"
|
||||
#include "led-mini2440.h"
|
||||
|
|
@ -121,6 +125,12 @@ static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS * SD_BLOCK_SIZE]
|
|||
__attribute__((aligned(32)));
|
||||
static unsigned char * uncached_buffer;
|
||||
|
||||
static inline void mci_delay(void)
|
||||
{
|
||||
int i = 0xffff;
|
||||
while (i--)
|
||||
asm volatile ("nop\n");
|
||||
}
|
||||
|
||||
/* TODO: should be in target include file */
|
||||
/*****************************************************************************
|
||||
|
|
@ -133,12 +143,6 @@ static unsigned char * uncached_buffer;
|
|||
/*****************************************************************************
|
||||
Functions specific to S3C2440 SoC
|
||||
*****************************************************************************/
|
||||
static inline void mci_delay(void)
|
||||
{
|
||||
/* Does this get optimised out ? */
|
||||
int i = 0xffff;
|
||||
while(i--) ;
|
||||
}
|
||||
|
||||
#ifdef SD_DEBUG
|
||||
static unsigned reg_copy[16], reg_copy2[16];
|
||||
|
|
@ -163,7 +167,7 @@ static void dump_regs (unsigned *regs1, unsigned *regs2)
|
|||
{
|
||||
diff = *regs1 ^ *regs2;
|
||||
if (diff)
|
||||
uart_printf ("%8x %8x %8x %8x\n", sdi_reg, *regs1, *regs2, diff );
|
||||
dbgprintf ("%8x %8x %8x %8x\n", sdi_reg, *regs1, *regs2, diff );
|
||||
regs1++;
|
||||
regs2++;
|
||||
sdi_reg++;
|
||||
|
|
@ -174,7 +178,7 @@ static void dump_regs (unsigned *regs1, unsigned *regs2)
|
|||
static void debug_r1(int cmd)
|
||||
{
|
||||
#if defined(SD_DEBUG)
|
||||
uart_printf("CMD%2.2d:SDICSTA=%04x [%c%c%c%c%c-%c%c%c%c%c%c%c] SDIRSP0=%08x [%d %s] \n",
|
||||
dbgprintf("CMD%2.2d:SDICSTA=%04x [%c%c%c%c%c-%c%c%c%c%c%c%c] SDIRSP0=%08x [%d %s] \n",
|
||||
cmd,
|
||||
SDICSTA,
|
||||
(SDICSTA & S3C2410_SDICMDSTAT_CRCFAIL) ? 'C' : ' ',
|
||||
|
|
@ -493,10 +497,25 @@ static int sd_init_card(const int card_no)
|
|||
/*****************************************************************************/
|
||||
#ifdef HAVE_HOTSWAP
|
||||
|
||||
static int sd1_oneshot_callback(struct timeout *tmo)
|
||||
{
|
||||
(void)tmo;
|
||||
|
||||
/* This is called only if the state was stable for 300ms - check state
|
||||
* and post appropriate event. */
|
||||
if (card_detect_target())
|
||||
{
|
||||
queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
|
||||
}
|
||||
else
|
||||
queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool card_detect_target(void)
|
||||
{
|
||||
/* TODO - use interrupt on change? */
|
||||
#ifdef MINI2440
|
||||
#ifdef MINI2440
|
||||
return (GPGDAT & SD_CD) == 0;
|
||||
#else
|
||||
#error Unsupported target
|
||||
|
|
@ -505,18 +524,30 @@ bool card_detect_target(void)
|
|||
|
||||
void card_enable_monitoring_target(bool on)
|
||||
{
|
||||
(void)on;
|
||||
/* TODO */
|
||||
if (on)
|
||||
{ /* enable external irq 8-23 on the internal interrupt controller */
|
||||
INTMSK &= ~1<<5;
|
||||
/* enable GPG8 IRQ on the external interrupt controller */
|
||||
EINTMASK &= ~(1<<16);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* mask internal and external IRQs */
|
||||
INTMSK |= 1<<5;
|
||||
EINTMASK |= (1<<16);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void EXT0(void)
|
||||
void EINT8_23(void)
|
||||
{
|
||||
static struct timeout sd1_oneshot;
|
||||
|
||||
/* TODO */
|
||||
EINTPEND = (1<<16); /* ack irq on external, then internal irq controller */
|
||||
SRCPND = (1<<5);
|
||||
INTPND = (1<<5);
|
||||
/* add task to inform the system about the SD insertion
|
||||
* sanity check if it's still inserted after 300ms */
|
||||
timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool sd_removable(IF_MD_NONVOID(int card_no))
|
||||
{
|
||||
|
|
@ -569,9 +600,52 @@ static void sd_thread(void)
|
|||
while (1)
|
||||
{
|
||||
queue_wait_w_tmo(&sd_queue, &ev, HZ);
|
||||
|
||||
switch ( ev.id )
|
||||
{
|
||||
#ifdef HAVE_HOTSWAP
|
||||
case SYS_HOTSWAP_INSERTED:
|
||||
case SYS_HOTSWAP_EXTRACTED:
|
||||
{
|
||||
int success = 1;
|
||||
fat_lock(); /* lock-out FAT activity first -
|
||||
prevent deadlocking via disk_mount that
|
||||
would cause a reverse-order attempt with
|
||||
another thread */
|
||||
mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
|
||||
into driver that bypass the fat cache */
|
||||
|
||||
/* We now have exclusive control of fat cache and ata */
|
||||
|
||||
disk_unmount(0); /* release "by force", ensure file
|
||||
descriptors aren't leaked and any busy
|
||||
ones are invalid if mounting */
|
||||
|
||||
/* Force card init for new card, re-init for re-inserted one or
|
||||
* clear if the last attempt to init failed with an error. */
|
||||
card_info[0].initialized = 0;
|
||||
|
||||
if (ev.id == SYS_HOTSWAP_INSERTED)
|
||||
{
|
||||
/* FIXME: once sd_enabled is implement properly,
|
||||
* reinitializing the controllers might be needed */
|
||||
sd_enable(true);
|
||||
if (success < 0) /* initialisation failed */
|
||||
panicf("SD init failed : %d", success);
|
||||
success = disk_mount(0); /* 0 if fail */
|
||||
}
|
||||
|
||||
/* notify the system about the changed filesystems
|
||||
*/
|
||||
if (success)
|
||||
queue_broadcast(SYS_FS_CHANGED, 0);
|
||||
|
||||
/* Access is now safe */
|
||||
mutex_unlock(&sd_mtx);
|
||||
fat_unlock();
|
||||
sd_enable(false);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -605,12 +679,9 @@ static int sd_wait_for_state(const int card_no, unsigned int state)
|
|||
}
|
||||
}
|
||||
|
||||
static int sd_transfer_sectors(IF_MD2(int card_no,) unsigned long start,
|
||||
static int sd_transfer_sectors(int card_no, unsigned long start,
|
||||
int count, void* buf, const bool write)
|
||||
{
|
||||
#ifndef HAVE_MULTIDRIVE
|
||||
const int card_no = 0;
|
||||
#endif
|
||||
int ret = EC_OK;
|
||||
unsigned loops = 0;
|
||||
struct dma_request request;
|
||||
|
|
@ -672,9 +743,9 @@ static int sd_transfer_sectors(IF_MD2(int card_no,) unsigned long start,
|
|||
else
|
||||
SDIDCON |= S3C2410_SDIDCON_RXAFTERCMD | S3C2410_SDIDCON_XFER_RXSTART;
|
||||
|
||||
SDIDSTA |= S3C2410_SDIDSTA_CLEAR_BITS; /* needed to clear int */
|
||||
SRCPND = SDI_MASK;
|
||||
INTPND = SDI_MASK;
|
||||
SDIDSTA |= S3C2410_SDIDSTA_CLEAR_BITS; /* needed to clear int */
|
||||
SRCPND = SDI_MASK;
|
||||
INTPND = SDI_MASK;
|
||||
|
||||
/* Initiate read/write command */
|
||||
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,
|
|||
{
|
||||
status = SDIDSTA;
|
||||
}
|
||||
uart_printf("%x \n", status);
|
||||
dbgprintf("%x \n", status);
|
||||
#endif
|
||||
if( transfer_error[card_no] & S3C2410_SDIDSTA_XFERFINISH )
|
||||
{
|
||||
|
|
@ -805,7 +876,12 @@ int sd_read_sectors(IF_MD2(int card_no,) unsigned long start, int incount,
|
|||
#else
|
||||
dbgprintf ("sd_read %x %d\n", start, incount);
|
||||
#endif
|
||||
ret = sd_transfer_sectors(IF_MD2(card_no,) start, incount, inbuf, false);
|
||||
#ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
|
||||
if (!card_detect_target())
|
||||
ret = 0; /* assume success */
|
||||
else
|
||||
#endif
|
||||
ret = sd_transfer_sectors(card_no, start, incount, inbuf, false);
|
||||
dbgprintf ("sd_read, ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -827,9 +903,14 @@ int sd_write_sectors(IF_MD2(int card_no,) unsigned long start, int count,
|
|||
dbgprintf ("sd_write %d %x %d\n", card_no, start, count);
|
||||
#else
|
||||
dbgprintf ("sd_write %x %d\n", start, count);
|
||||
#endif
|
||||
return sd_transfer_sectors(IF_MD2(card_no,) start, count, (void*)outbuf, true);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
|
||||
if (!card_detect_target())
|
||||
return 0; /* assume success */
|
||||
else
|
||||
#endif
|
||||
return sd_transfer_sectors(card_no, start, count, (void*)outbuf, true);
|
||||
#endif
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -870,7 +951,24 @@ int sd_init(void)
|
|||
sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
|
||||
|
||||
uncached_buffer = UNCACHED_ADDR(&aligned_buffer[0]);
|
||||
|
||||
|
||||
#ifdef HAVE_HOTSWAP
|
||||
/*
|
||||
* prepare detecting of SD insertion (not extraction) */
|
||||
unsigned long for_extint = EXTINT2;
|
||||
unsigned long for_gpgcon = GPGCON;
|
||||
for_extint &= ~0x7;
|
||||
#ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
|
||||
for_extint |= 0x2; /* detect falling edge only (0 means SD inserted) */
|
||||
#else
|
||||
for_extint |= 0x3; /* detect both, raising and falling, edges */
|
||||
#endif
|
||||
for_gpgcon &= ~(0x3<<16);
|
||||
for_gpgcon |= (0x2<<16); /* enable interrupt on pin 8 */
|
||||
EXTINT2 = for_extint;
|
||||
GPGCON = for_gpgcon;
|
||||
#endif
|
||||
|
||||
initialized = true;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue