mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-10 13:45:10 -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
|
|
@ -39,11 +39,11 @@
|
||||||
/* define the storage type */
|
/* define the storage type */
|
||||||
#define CONFIG_STORAGE STORAGE_SD
|
#define CONFIG_STORAGE STORAGE_SD
|
||||||
|
|
||||||
/*
|
|
||||||
#define HAVE_MULTIDRIVE
|
#define HAVE_MULTIDRIVE
|
||||||
#define NUM_DRIVES 2
|
#define NUM_DRIVES 1 // no access to NAND yet
|
||||||
#define HAVE_HOTSWAP
|
#define HAVE_HOTSWAP
|
||||||
*/
|
#define HAVE_HOTSWAP_STORAGE_AS_MAIN
|
||||||
|
#define INCLUDE_TIMEOUT_API
|
||||||
|
|
||||||
/* Disk storage */
|
/* Disk storage */
|
||||||
/* define this if you have a disk storage, i.e. something
|
/* define this if you have a disk storage, i.e. something
|
||||||
|
|
|
||||||
|
|
@ -19,18 +19,22 @@
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define SD_DEBUG
|
//#define SD_DEBUG
|
||||||
|
|
||||||
#include "sd.h"
|
#include "sd.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "hotswap.h"
|
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
|
|
||||||
#ifdef SD_DEBUG
|
#ifdef SD_DEBUG
|
||||||
#include "uart-s3c2440.h"
|
#include "uart-s3c2440.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_HOTSWAP
|
||||||
|
#include "hotswap.h"
|
||||||
|
#include "disk.h"
|
||||||
|
#include "fat.h"
|
||||||
|
#endif
|
||||||
#include "dma-target.h"
|
#include "dma-target.h"
|
||||||
#include "system-target.h"
|
#include "system-target.h"
|
||||||
#include "led-mini2440.h"
|
#include "led-mini2440.h"
|
||||||
|
|
@ -121,6 +125,12 @@ static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS * SD_BLOCK_SIZE]
|
||||||
__attribute__((aligned(32)));
|
__attribute__((aligned(32)));
|
||||||
static unsigned char * uncached_buffer;
|
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 */
|
/* TODO: should be in target include file */
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
@ -133,12 +143,6 @@ static unsigned char * uncached_buffer;
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
Functions specific to S3C2440 SoC
|
Functions specific to S3C2440 SoC
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
static inline void mci_delay(void)
|
|
||||||
{
|
|
||||||
/* Does this get optimised out ? */
|
|
||||||
int i = 0xffff;
|
|
||||||
while(i--) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SD_DEBUG
|
#ifdef SD_DEBUG
|
||||||
static unsigned reg_copy[16], reg_copy2[16];
|
static unsigned reg_copy[16], reg_copy2[16];
|
||||||
|
|
@ -163,7 +167,7 @@ static void dump_regs (unsigned *regs1, unsigned *regs2)
|
||||||
{
|
{
|
||||||
diff = *regs1 ^ *regs2;
|
diff = *regs1 ^ *regs2;
|
||||||
if (diff)
|
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++;
|
regs1++;
|
||||||
regs2++;
|
regs2++;
|
||||||
sdi_reg++;
|
sdi_reg++;
|
||||||
|
|
@ -174,7 +178,7 @@ static void dump_regs (unsigned *regs1, unsigned *regs2)
|
||||||
static void debug_r1(int cmd)
|
static void debug_r1(int cmd)
|
||||||
{
|
{
|
||||||
#if defined(SD_DEBUG)
|
#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,
|
cmd,
|
||||||
SDICSTA,
|
SDICSTA,
|
||||||
(SDICSTA & S3C2410_SDICMDSTAT_CRCFAIL) ? 'C' : ' ',
|
(SDICSTA & S3C2410_SDICMDSTAT_CRCFAIL) ? 'C' : ' ',
|
||||||
|
|
@ -493,10 +497,25 @@ static int sd_init_card(const int card_no)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
#ifdef HAVE_HOTSWAP
|
#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)
|
bool card_detect_target(void)
|
||||||
{
|
{
|
||||||
/* TODO - use interrupt on change? */
|
/* TODO - use interrupt on change? */
|
||||||
#ifdef MINI2440
|
#ifdef MINI2440
|
||||||
return (GPGDAT & SD_CD) == 0;
|
return (GPGDAT & SD_CD) == 0;
|
||||||
#else
|
#else
|
||||||
#error Unsupported target
|
#error Unsupported target
|
||||||
|
|
@ -505,18 +524,30 @@ bool card_detect_target(void)
|
||||||
|
|
||||||
void card_enable_monitoring_target(bool on)
|
void card_enable_monitoring_target(bool on)
|
||||||
{
|
{
|
||||||
(void)on;
|
if (on)
|
||||||
/* TODO */
|
{ /* 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 EINT8_23(void)
|
||||||
void EXT0(void)
|
|
||||||
{
|
{
|
||||||
static struct timeout sd1_oneshot;
|
static struct timeout sd1_oneshot;
|
||||||
|
EINTPEND = (1<<16); /* ack irq on external, then internal irq controller */
|
||||||
/* TODO */
|
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))
|
bool sd_removable(IF_MD_NONVOID(int card_no))
|
||||||
{
|
{
|
||||||
|
|
@ -569,9 +600,52 @@ static void sd_thread(void)
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
queue_wait_w_tmo(&sd_queue, &ev, HZ);
|
queue_wait_w_tmo(&sd_queue, &ev, HZ);
|
||||||
|
|
||||||
switch ( ev.id )
|
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)
|
int count, void* buf, const bool write)
|
||||||
{
|
{
|
||||||
#ifndef HAVE_MULTIDRIVE
|
|
||||||
const int card_no = 0;
|
|
||||||
#endif
|
|
||||||
int ret = EC_OK;
|
int ret = EC_OK;
|
||||||
unsigned loops = 0;
|
unsigned loops = 0;
|
||||||
struct dma_request request;
|
struct dma_request request;
|
||||||
|
|
@ -672,9 +743,9 @@ static int sd_transfer_sectors(IF_MD2(int card_no,) unsigned long start,
|
||||||
else
|
else
|
||||||
SDIDCON |= S3C2410_SDIDCON_RXAFTERCMD | S3C2410_SDIDCON_XFER_RXSTART;
|
SDIDCON |= S3C2410_SDIDCON_RXAFTERCMD | S3C2410_SDIDCON_XFER_RXSTART;
|
||||||
|
|
||||||
SDIDSTA |= S3C2410_SDIDSTA_CLEAR_BITS; /* needed to clear int */
|
SDIDSTA |= S3C2410_SDIDSTA_CLEAR_BITS; /* needed to clear int */
|
||||||
SRCPND = SDI_MASK;
|
SRCPND = SDI_MASK;
|
||||||
INTPND = SDI_MASK;
|
INTPND = SDI_MASK;
|
||||||
|
|
||||||
/* Initiate read/write command */
|
/* Initiate read/write command */
|
||||||
if(!send_cmd(card_no, cmd, start_addr, MCI_ARG | MCI_RESP, NULL))
|
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;
|
status = SDIDSTA;
|
||||||
}
|
}
|
||||||
uart_printf("%x \n", status);
|
dbgprintf("%x \n", status);
|
||||||
#endif
|
#endif
|
||||||
if( transfer_error[card_no] & S3C2410_SDIDSTA_XFERFINISH )
|
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
|
#else
|
||||||
dbgprintf ("sd_read %x %d\n", start, incount);
|
dbgprintf ("sd_read %x %d\n", start, incount);
|
||||||
#endif
|
#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);
|
dbgprintf ("sd_read, ret=%d\n", ret);
|
||||||
return 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);
|
dbgprintf ("sd_write %d %x %d\n", card_no, start, count);
|
||||||
#else
|
#else
|
||||||
dbgprintf ("sd_write %x %d\n", start, count);
|
dbgprintf ("sd_write %x %d\n", start, count);
|
||||||
#endif
|
#endif
|
||||||
return sd_transfer_sectors(IF_MD2(card_no,) start, count, (void*)outbuf, true);
|
#ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
|
||||||
#endif
|
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));
|
sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
|
||||||
|
|
||||||
uncached_buffer = UNCACHED_ADDR(&aligned_buffer[0]);
|
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;
|
initialized = true;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue