From 9f336217c28dd16daeafc05e5019db0e0dd5c350 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Sun, 29 Jul 2018 04:46:04 +0200 Subject: 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 --- firmware/target/arm/as3525/sd-as3525.c | 95 +++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 30 deletions(-) (limited to 'firmware/target/arm/as3525') diff --git a/firmware/target/arm/as3525/sd-as3525.c b/firmware/target/arm/as3525/sd-as3525.c index 494a76a782..86286fa985 100644 --- a/firmware/target/arm/as3525/sd-as3525.c +++ b/firmware/target/arm/as3525/sd-as3525.c @@ -89,6 +89,8 @@ | MCI_CMD_CRC_FAIL) #define MCI_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80)) + +#define IDE_INTERFACE_CLK (1<<6) /* non AHB interface */ /* volumes */ #define INTERNAL_AS3525 0 /* embedded SD card */ #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]; -/* 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_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 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) @@ -197,17 +210,33 @@ static void enable_controller(bool on) #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)); -#else - return false; + + if (drive == INTERNAL_AS3525) + { +#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 } - #ifdef HAVE_HOTSWAP 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; } +/* MCI_CLOCK = MCLK / 2x(ClkDiv[bits 7:0]+1) */ #define MCI_FULLSPEED (MCI_CLOCK_ENABLE | MCI_CLOCK_BYPASS) /* MCLK */ #define MCI_HALFSPEED (MCI_CLOCK_ENABLE) /* MCLK/2 */ #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 */ /* 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)) return -1; mci_delay(); @@ -393,10 +423,10 @@ static int sd_init_card(const int drive) if(sd_wait_for_tran_state(drive)) 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)) 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 */ /* 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) else /* 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 /* 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 ret; - CGU_IDE = (1<<6) /* enable non AHB interface*/ + CGU_IDE = IDE_INTERFACE_CLK /* enable interface */ | (AS3525_IDE_DIV << 2) | AS3525_CLK_PLLA; /* clock source = PLLA */ @@ -540,7 +571,9 @@ int sd_init(void) /* init mutex */ mutex_init(&sd_mtx); - enable_controller(false); + for (int i = 0; i < NUM_DRIVES ; i++) + enable_controller(false, i); + return 0; } @@ -656,7 +689,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, unsigned long response; bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); - enable_controller(true); + enable_controller(true, drive); led(true); if (card_info[drive].initialized <= 0) @@ -692,17 +725,15 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, else discard_dcache_range(buf, count * SECTOR_SIZE); } - - while(count) + const int cmd = write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; + while(count > 0) { /* 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. */ unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */ void *dma_buf; - const int cmd = - write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; + unsigned long bank_start = start; - unsigned long status; /* Only switch banks for internal storage */ 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*/ #ifdef HAVE_MULTIDRIVE if((drive == SD_SLOT_AS3525) && !hs_card) - { - int write_delay = 125; - while(write_delay--); - } + udelay(4); #endif } else @@ -804,7 +832,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, 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; goto sd_transfer_error; @@ -831,7 +859,7 @@ sd_transfer_error: sd_transfer_error_nodma: led(false); - enable_controller(false); + enable_controller(false, drive); if (ret) /* error */ 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)) 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; #ifdef HAVE_MULTIDRIVE info->mci_sd = MCI_SD; #endif - enable_controller(false); + + for (int i = 0; i < NUM_DRIVES ; i++) + enable_controller(false, i); + mutex_unlock(&sd_mtx); } @@ -948,10 +982,10 @@ int sd_event(long id, intptr_t data) if (id == SYS_HOTSWAP_INSERTED) { - enable_controller(true); + enable_controller(true, data); init_pl180_controller(data); rc = sd_init_card(data); - enable_controller(false); + enable_controller(false, data); } mutex_unlock(&sd_mtx); @@ -968,3 +1002,4 @@ int sd_event(long id, intptr_t data) return rc; } + -- cgit v1.2.3