Sansa AS3525V1 Sd Interface implement powersave mode

This patch cleans up the sd driver for the V1 sansas
powersave implemented for the sd interface

Change-Id: I3d864f7aa304cf792cc65fa4ff06c1e52fbed329
This commit is contained in:
William Wilgus 2018-07-29 04:46:04 +02:00
parent f45db552f3
commit 9f336217c2

View file

@ -89,6 +89,8 @@
| MCI_CMD_CRC_FAIL) | MCI_CMD_CRC_FAIL)
#define MCI_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80)) #define MCI_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80))
#define IDE_INTERFACE_CLK (1<<6) /* non AHB interface */
/* volumes */ /* volumes */
#define INTERNAL_AS3525 0 /* embedded SD card */ #define INTERNAL_AS3525 0 /* embedded SD card */
#define SD_SLOT_AS3525 1 /* SD slot if present */ #define SD_SLOT_AS3525 1 /* SD slot if present */
@ -109,7 +111,8 @@ static void init_pl180_controller(const int drive);
static tCardInfo card_info[NUM_DRIVES]; static tCardInfo card_info[NUM_DRIVES];
/* maximum timeouts recommanded in the SD Specification v2.00 */ /* maximum timeouts recommended in the SD Specification v2.00 */
/* MCI_DATA_TIMER register data timeout in card bus clock periods */
#define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */ #define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */
#define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */ #define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */
@ -143,7 +146,17 @@ static unsigned char *uncached_buffer = AS3525_UNCACHED_ADDR(&aligned_buffer[0])
static inline void mci_delay(void) { udelay(1000) ; } static inline void mci_delay(void) { udelay(1000) ; }
static void enable_controller(bool on) static inline bool card_detect_target(void)
{
#if defined(HAVE_MULTIDRIVE)
return !(GPIOA_PIN(2));
#else
return false;
#endif
}
#if defined(HAVE_MULTIDRIVE) || defined(HAVE_HOTSWAP)
static void enable_controller_mci(bool on)
{ {
#if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE)
@ -197,16 +210,32 @@ static void enable_controller(bool on)
#endif #endif
} }
} }
#endif /* defined(HAVE_MULTIDRIVE) || defined(HAVE_HOTSWAP) */
static inline bool card_detect_target(void) /* AMS v1 have two different drive interfaces MCI_SD(XPD) and GGU_IDE */
static void enable_controller(bool on, const int drive)
{ {
#if defined(HAVE_MULTIDRIVE)
return !(GPIOA_PIN(2)); if (drive == INTERNAL_AS3525)
#else {
return false; #ifndef BOOTLOADER
if (on)
{
bitset32(&CGU_PERI, CGU_NAF_CLOCK_ENABLE);
CGU_IDE |= IDE_INTERFACE_CLK; /* interface enable */
}
else
{
CGU_IDE &= ~(IDE_INTERFACE_CLK); /* interface disable */
bitclr32(&CGU_PERI, CGU_NAF_CLOCK_ENABLE);
}
#endif
}
#if defined(HAVE_MULTIDRIVE) || defined(HAVE_HOTSWAP)
else
enable_controller_mci(on);
#endif #endif
} }
#ifdef HAVE_HOTSWAP #ifdef HAVE_HOTSWAP
static int sd1_oneshot_callback(struct timeout *tmo) static int sd1_oneshot_callback(struct timeout *tmo)
@ -326,6 +355,7 @@ static bool send_cmd(const int drive, const int cmd, const int arg,
return false; return false;
} }
/* MCI_CLOCK = MCLK / 2x(ClkDiv[bits 7:0]+1) */
#define MCI_FULLSPEED (MCI_CLOCK_ENABLE | MCI_CLOCK_BYPASS) /* MCLK */ #define MCI_FULLSPEED (MCI_CLOCK_ENABLE | MCI_CLOCK_BYPASS) /* MCLK */
#define MCI_HALFSPEED (MCI_CLOCK_ENABLE) /* MCLK/2 */ #define MCI_HALFSPEED (MCI_CLOCK_ENABLE) /* MCLK/2 */
#define MCI_QUARTERSPEED (MCI_CLOCK_ENABLE | 1) /* MCLK/4 */ #define MCI_QUARTERSPEED (MCI_CLOCK_ENABLE | 1) /* MCLK/4 */
@ -345,7 +375,7 @@ static int sd_init_card(const int drive)
/* 100 - 400kHz clock required for Identification Mode */ /* 100 - 400kHz clock required for Identification Mode */
/* Start of Card Identification Mode ************************************/ /* Start of Card Identification Mode ************************************/
/* CMD0 Go Idle */ /* CMD0 Go Idle -- all card functions switch back to default */
if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL))
return -1; return -1;
mci_delay(); mci_delay();
@ -393,10 +423,10 @@ static int sd_init_card(const int drive)
if(sd_wait_for_tran_state(drive)) if(sd_wait_for_tran_state(drive))
return -6; return -6;
/* CMD6 */ /* CMD6 0xf indicates no influence, [3:0],0x1 - HS Access*/
if(!send_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL)) if(!send_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL))
return -7; return -7;
sleep(HZ/10); sleep(HZ/10);/* need to wait at least 8 clock periods */
/* go back to STBY state so we can read csd */ /* go back to STBY state so we can read csd */
/* CMD7 w/rca=0: Deselect card to put it in STBY state */ /* CMD7 w/rca=0: Deselect card to put it in STBY state */
@ -423,7 +453,8 @@ static int sd_init_card(const int drive)
#if defined(HAVE_MULTIDRIVE) #if defined(HAVE_MULTIDRIVE)
else else
/* MCICLK = PCLK/2 = 31MHz(HS) or PCLK/4 = 15.5 Mhz (STD)*/ /* MCICLK = PCLK/2 = 31MHz(HS) or PCLK/4 = 15.5 Mhz (STD)*/
MCI_CLOCK(drive) = (hs_card ? MCI_HALFSPEED : MCI_QUARTERSPEED); MCI_CLOCK(drive) = (hs_card ? MCI_HALFSPEED : MCI_QUARTERSPEED) |
MCI_CLOCK_POWERSAVE; /* SD supports powersave */
#endif #endif
/* CMD7 w/rca: Select card to put it in TRAN state */ /* CMD7 w/rca: Select card to put it in TRAN state */
@ -517,7 +548,7 @@ static void init_pl180_controller(const int drive)
int sd_init(void) int sd_init(void)
{ {
int ret; int ret;
CGU_IDE = (1<<6) /* enable non AHB interface*/ CGU_IDE = IDE_INTERFACE_CLK /* enable interface */
| (AS3525_IDE_DIV << 2) | (AS3525_IDE_DIV << 2)
| AS3525_CLK_PLLA; /* clock source = PLLA */ | AS3525_CLK_PLLA; /* clock source = PLLA */
@ -540,7 +571,9 @@ int sd_init(void)
/* init mutex */ /* init mutex */
mutex_init(&sd_mtx); mutex_init(&sd_mtx);
enable_controller(false); for (int i = 0; i < NUM_DRIVES ; i++)
enable_controller(false, i);
return 0; return 0;
} }
@ -656,7 +689,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start,
unsigned long response; unsigned long response;
bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1));
enable_controller(true); enable_controller(true, drive);
led(true); led(true);
if (card_info[drive].initialized <= 0) if (card_info[drive].initialized <= 0)
@ -692,17 +725,15 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start,
else else
discard_dcache_range(buf, count * SECTOR_SIZE); discard_dcache_range(buf, count * SECTOR_SIZE);
} }
const int cmd = write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK;
while(count) while(count > 0)
{ {
/* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH
* register, so we have to transfer maximum 127 sectors at a time. */ * register, so we have to transfer maximum 127 sectors at a time. */
unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */ unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */
void *dma_buf; void *dma_buf;
const int cmd =
write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK;
unsigned long bank_start = start; unsigned long bank_start = start;
unsigned long status;
/* Only switch banks for internal storage */ /* Only switch banks for internal storage */
if(drive == INTERNAL_AS3525) if(drive == INTERNAL_AS3525)
@ -770,10 +801,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start,
/*Small delay for writes prevents data crc failures at lower freqs*/ /*Small delay for writes prevents data crc failures at lower freqs*/
#ifdef HAVE_MULTIDRIVE #ifdef HAVE_MULTIDRIVE
if((drive == SD_SLOT_AS3525) && !hs_card) if((drive == SD_SLOT_AS3525) && !hs_card)
{ udelay(4);
int write_delay = 125;
while(write_delay--);
}
#endif #endif
} }
else else
@ -804,7 +832,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start,
last_disk_activity = current_tick; last_disk_activity = current_tick;
if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP, &status)) if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP, &response))
{ {
ret = -4*20; ret = -4*20;
goto sd_transfer_error; goto sd_transfer_error;
@ -831,7 +859,7 @@ sd_transfer_error:
sd_transfer_error_nodma: sd_transfer_error_nodma:
led(false); led(false);
enable_controller(false); enable_controller(false, drive);
if (ret) /* error */ if (ret) /* error */
card_info[drive].initialized = 0; card_info[drive].initialized = 0;
@ -922,12 +950,18 @@ void ams_sd_get_debug_info(struct ams_sd_debug_info *info)
#define MCI_SD *((volatile unsigned long *)(SD_MCI_BASE + 0x04)) #define MCI_SD *((volatile unsigned long *)(SD_MCI_BASE + 0x04))
mutex_lock(&sd_mtx); mutex_lock(&sd_mtx);
enable_controller(true); /* must be on to read regs */
for (int i = 0; i < NUM_DRIVES ; i++)
enable_controller(true, i); /* must be on to read regs */
info->mci_nand = MCI_NAND; info->mci_nand = MCI_NAND;
#ifdef HAVE_MULTIDRIVE #ifdef HAVE_MULTIDRIVE
info->mci_sd = MCI_SD; info->mci_sd = MCI_SD;
#endif #endif
enable_controller(false);
for (int i = 0; i < NUM_DRIVES ; i++)
enable_controller(false, i);
mutex_unlock(&sd_mtx); mutex_unlock(&sd_mtx);
} }
@ -948,10 +982,10 @@ int sd_event(long id, intptr_t data)
if (id == SYS_HOTSWAP_INSERTED) if (id == SYS_HOTSWAP_INSERTED)
{ {
enable_controller(true); enable_controller(true, data);
init_pl180_controller(data); init_pl180_controller(data);
rc = sd_init_card(data); rc = sd_init_card(data);
enable_controller(false); enable_controller(false, data);
} }
mutex_unlock(&sd_mtx); mutex_unlock(&sd_mtx);
@ -968,3 +1002,4 @@ int sd_event(long id, intptr_t data)
return rc; return rc;
} }