summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/as3525/ascodec-as3525.c31
-rw-r--r--firmware/target/arm/as3525/clock-target.h28
-rw-r--r--firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c23
-rw-r--r--firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c24
-rw-r--r--firmware/target/arm/as3525/sd-as3525.c138
-rw-r--r--firmware/target/arm/as3525/sd-as3525v2.c26
-rw-r--r--firmware/target/arm/as3525/system-as3525.c70
-rw-r--r--firmware/target/arm/as3525/system-target.h20
8 files changed, 51 insertions, 309 deletions
diff --git a/firmware/target/arm/as3525/ascodec-as3525.c b/firmware/target/arm/as3525/ascodec-as3525.c
index d23859e420..14c3ee7a36 100644
--- a/firmware/target/arm/as3525/ascodec-as3525.c
+++ b/firmware/target/arm/as3525/ascodec-as3525.c
@@ -623,25 +623,11 @@ void i2c_init(void)
623 /* required function but called too late for our needs */ 623 /* required function but called too late for our needs */
624} 624}
625 625
626static void i2c_set_prescaler(unsigned int prescaler)
627{
628 int oldlevel = disable_interrupt_save(IRQ_FIQ_STATUS);
629 /* must be on to write regs */
630 bool i2c_enabled = bitset32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE) &
631 CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE;
632
633 I2C2_CPSR0 = prescaler & 0xFF; /* 8 lsb */
634 I2C2_CPSR1 = (prescaler >> 8) & 0x3; /* 2 msb */
635
636 if (!i2c_enabled) /* put it back how we found it */
637 bitclr32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE);
638
639 restore_irq(oldlevel);
640}
641
642/* initialises the internal i2c bus and prepares for transfers to the codec */ 626/* initialises the internal i2c bus and prepares for transfers to the codec */
643void ascodec_init(void) 627void ascodec_init(void)
644{ 628{
629 int prescaler;
630
645 ll_init(&req_list); 631 ll_init(&req_list);
646 mutex_init(&as_mtx); 632 mutex_init(&as_mtx);
647 ascodec_async_init(&as_audio_req, ascodec_int_audio_cb, 0); 633 ascodec_async_init(&as_audio_req, ascodec_int_audio_cb, 0);
@@ -651,7 +637,9 @@ void ascodec_init(void)
651 bitset32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE); 637 bitset32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE);
652 638
653 /* prescaler for i2c clock */ 639 /* prescaler for i2c clock */
654 i2c_set_prescaler(AS3525_I2C_PRESCALER); 640 prescaler = AS3525_I2C_PRESCALER;
641 I2C2_CPSR0 = prescaler & 0xFF; /* 8 lsb */
642 I2C2_CPSR1 = (prescaler >> 8) & 0x3; /* 2 msb */
655 643
656 /* set i2c slave address of codec part */ 644 /* set i2c slave address of codec part */
657 I2C2_SLAD0 = AS3514_I2C_ADDR << 1; 645 I2C2_SLAD0 = AS3514_I2C_ADDR << 1;
@@ -702,12 +690,3 @@ void ams_i2c_get_debug_cpsr(unsigned int *i2c_cpsr)
702 690
703 restore_irq(oldlevel); 691 restore_irq(oldlevel);
704} 692}
705
706#if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_I2C)
707/* declared in system-as3525.c */
708void ams_i2c_set_low_speed(bool slow)
709{
710 i2c_set_prescaler(slow ? AS3525_I2C_PRESCALER_MAX : AS3525_I2C_PRESCALER);
711}
712#endif
713
diff --git a/firmware/target/arm/as3525/clock-target.h b/firmware/target/arm/as3525/clock-target.h
index c45529dfda..7f6b17eff4 100644
--- a/firmware/target/arm/as3525/clock-target.h
+++ b/firmware/target/arm/as3525/clock-target.h
@@ -158,32 +158,22 @@
158#endif /* CONFIG_CPU */ 158#endif /* CONFIG_CPU */
159 159
160 /* PCLK as Source */ 160 /* PCLK as Source */
161 #define AS3525_DBOP_DIV (CLK_DIV(AS3525_PCLK_FREQ, AS3525_DBOP_FREQ) - 1) /*div=1/(n+1)*/ 161 #define AS3525_DBOP_DIV (CLK_DIV(AS3525_PCLK_FREQ, AS3525_DBOP_FREQ) - 1) /*div=1/(n+1)*/
162 #define AS3525_I2C_PRESCALER CLK_DIV(AS3525_PCLK_FREQ, AS3525_I2C_FREQ) 162 #define AS3525_I2C_PRESCALER CLK_DIV(AS3525_PCLK_FREQ, AS3525_I2C_FREQ)
163 #define AS3525_I2C_PRESCALER_MAX 0xFF | 0x300 /* Max value for prescaler */ 163 #define AS3525_I2C_FREQ 400000
164 #define AS3525_I2C_FREQ 400000 164 #define AS3525_SD_IDENT_DIV ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ) / 2) - 1)
165 #define AS3525_SD_IDENT_DIV ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ) / 2) - 1) 165 #define AS3525_SD_IDENT_FREQ 400000 /* must be between 100 & 400 kHz */
166 #define AS3525_SD_IDENT_FREQ 400000 /* must be between 100 & 400 kHz */ 166 #define AS3525_SSP_PRESCALER ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SSP_FREQ) + 1) & ~1) /* must be an even number */
167 #define AS3525_SSP_PRESCALER ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SSP_FREQ) + 1) & ~1) /* must be an even number */ 167 #define AS3525_SSP_FREQ 12000000
168#if LCD_DEPTH > 1
169 #define AS3525_SSP_PRESCALER_MAX ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SSP_FREQ_MIN) + 1) & ~1)/* must be an even number */
170 #define AS3525_SSP_FREQ_MIN 2000000 /* 2 MHz gives a decent refresh rate on clipzip*/
171#else
172 #define AS3525_SSP_PRESCALER_MAX 0xFE & ~1 /*Max value for divider - must be an even number */
173 #define AS3525_SSP_FREQ_MIN AS3525_SSP_FREQ /* No set minimum we just use max divider */
174#endif
175 #define AS3525_SSP_FREQ 12000000
176 168
177#define AS3525_IDE_SEL AS3525_CLK_PLLA /* Input Source */ 169#define AS3525_IDE_SEL AS3525_CLK_PLLA /* Input Source */
178#define AS3525_IDE_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_IDE_FREQ) - 1)/*div=1/(n+1)*/ 170#define AS3525_IDE_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_IDE_FREQ) - 1)/*div=1/(n+1)*/
179#define AS3525_IDE_DIV_MAX 0xF /* Max value for divider */
180 171
181#if CONFIG_CPU == AS3525v2 172#if CONFIG_CPU == AS3525v2
182#define AS3525_MS_FREQ 120000000 173#define AS3525_MS_FREQ 120000000
183#define AS3525_MS_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_MS_FREQ) -1) 174#define AS3525_MS_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_MS_FREQ) -1)
184#define AS3525_SDSLOT_FREQ 24000000 175#define AS3525_SDSLOT_FREQ 24000000
185#define AS3525_SDSLOT_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_SDSLOT_FREQ) -1) 176#define AS3525_SDSLOT_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_SDSLOT_FREQ) -1)
186#define AS3525_SDSLOT_DIV_MAX 0xF /* Max value for divider */
187#define AS3525_IDE_FREQ 80000000 177#define AS3525_IDE_FREQ 80000000
188#else 178#else
189#define AS3525_IDE_FREQ 50000000 /* The OF uses 66MHz maximal freq */ 179#define AS3525_IDE_FREQ 50000000 /* The OF uses 66MHz maximal freq */
@@ -221,10 +211,6 @@
221#error SSP frequency is too low : clock divider will not fit ! 211#error SSP frequency is too low : clock divider will not fit !
222#endif 212#endif
223 213
224#if (((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SSP_FREQ_MIN)) + 1 ) & ~1) >= (1<<8) /* 8 bits */
225#error SSP_MIN frequency is too low : clock divider will not fit !
226#endif
227
228/* AS3525_SD_IDENT_FREQ */ 214/* AS3525_SD_IDENT_FREQ */
229#if ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ) / 2) - 1) >= (1<<8) /* 8 bits */ 215#if ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ) / 2) - 1) >= (1<<8) /* 8 bits */
230#error SD IDENTIFICATION frequency is too low : clock divider will not fit ! 216#error SD IDENTIFICATION frequency is too low : clock divider will not fit !
diff --git a/firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c b/firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c
index 7c0cfb5345..a50a9e5c80 100644
--- a/firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c
+++ b/firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c
@@ -26,25 +26,11 @@
26#include "system.h" 26#include "system.h"
27#include "cpu.h" 27#include "cpu.h"
28 28
29static void ssp_set_prescaler(unsigned int prescaler)
30{
31 int oldlevel = disable_interrupt_save(IRQ_FIQ_STATUS);
32 /* must be on to write regs */
33 bool ssp_enabled = bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE) &
34 CGU_SSP_CLOCK_ENABLE;
35 SSP_CPSR = prescaler;
36
37 if (!ssp_enabled) /* put it back how we found it */
38 bitclr32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE);
39
40 restore_irq(oldlevel);
41}
42
43int lcd_hw_init(void) 29int lcd_hw_init(void)
44{ 30{
45 bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE); 31 bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE);
46 32
47 ssp_set_prescaler(AS3525_SSP_PRESCALER); /* OF = 0x10 */ 33 SSP_CPSR = AS3525_SSP_PRESCALER; /* OF = 0x10 */
48 SSP_CR0 = (1<<7) | (1<<6) | 7; /* Motorola SPI frame format, 8 bits */ 34 SSP_CR0 = (1<<7) | (1<<6) | 7; /* Motorola SPI frame format, 8 bits */
49 SSP_CR1 = (1<<3) | (1<<1); /* SSP Operation enabled */ 35 SSP_CR1 = (1<<3) | (1<<1); /* SSP Operation enabled */
50 SSP_IMSC = 0; /* No interrupts */ 36 SSP_IMSC = 0; /* No interrupts */
@@ -129,10 +115,3 @@ void lcd_enable_power(bool onoff)
129#endif 115#endif
130} 116}
131 117
132#if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_DISP)
133/* declared in system-as3525.c */
134void ams_ssp_set_low_speed(bool slow)
135{
136 ssp_set_prescaler(slow ? AS3525_SSP_PRESCALER_MAX : AS3525_SSP_PRESCALER);
137}
138#endif
diff --git a/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c b/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
index 8a3df517fb..e17bfc421b 100644
--- a/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
+++ b/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
@@ -35,26 +35,12 @@ static int lcd_type;
35static bool lcd_enabled; 35static bool lcd_enabled;
36#endif 36#endif
37 37
38static void ssp_set_prescaler(unsigned int prescaler)
39{
40 int oldlevel = disable_interrupt_save(IRQ_FIQ_STATUS);
41 /* must be on to write regs */
42 bool ssp_enabled = bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE) &
43 CGU_SSP_CLOCK_ENABLE;
44 SSP_CPSR = prescaler;
45
46 if (!ssp_enabled) /* put it back how we found it */
47 bitclr32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE);
48
49 restore_irq(oldlevel);
50}
51
52/* initialises the host lcd hardware, returns the lcd type */ 38/* initialises the host lcd hardware, returns the lcd type */
53static int lcd_hw_init(void) 39static int lcd_hw_init(void)
54{ 40{
55 /* configure SSP */ 41 /* configure SSP */
56 bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE); 42 bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE);
57 ssp_set_prescaler(AS3525_SSP_PRESCALER); /* OF = 0x8 */ 43 SSP_CPSR = 4; /* TODO: use AS3525_SSP_PRESCALER, OF uses 8 */
58 SSP_CR0 = (0 << 8) | /* SCR, serial clock rate divider = 1 */ 44 SSP_CR0 = (0 << 8) | /* SCR, serial clock rate divider = 1 */
59 (1 << 7) | /* SPH, phase = 1 */ 45 (1 << 7) | /* SPH, phase = 1 */
60 (1 << 6) | /* SPO, polarity = 1 */ 46 (1 << 6) | /* SPO, polarity = 1 */
@@ -451,11 +437,3 @@ void lcd_update(void)
451{ 437{
452 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); 438 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
453} 439}
454
455#if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_DISP)
456/* declared in system-as3525.c */
457void ams_ssp_set_low_speed(bool slow)
458{
459 ssp_set_prescaler(slow ? AS3525_SSP_PRESCALER_MAX : AS3525_SSP_PRESCALER);
460}
461#endif
diff --git a/firmware/target/arm/as3525/sd-as3525.c b/firmware/target/arm/as3525/sd-as3525.c
index 9e4a86acbe..494a76a782 100644
--- a/firmware/target/arm/as3525/sd-as3525.c
+++ b/firmware/target/arm/as3525/sd-as3525.c
@@ -89,8 +89,6 @@
89 | MCI_CMD_CRC_FAIL) 89 | MCI_CMD_CRC_FAIL)
90 90
91#define MCI_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80)) 91#define MCI_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80))
92
93#define IDE_INTERFACE_CLK (1<<6) /* non AHB interface */
94/* volumes */ 92/* volumes */
95#define INTERNAL_AS3525 0 /* embedded SD card */ 93#define INTERNAL_AS3525 0 /* embedded SD card */
96#define SD_SLOT_AS3525 1 /* SD slot if present */ 94#define SD_SLOT_AS3525 1 /* SD slot if present */
@@ -111,8 +109,7 @@ static void init_pl180_controller(const int drive);
111 109
112static tCardInfo card_info[NUM_DRIVES]; 110static tCardInfo card_info[NUM_DRIVES];
113 111
114/* maximum timeouts recommended in the SD Specification v2.00 */ 112/* maximum timeouts recommanded in the SD Specification v2.00 */
115/* MCI_DATA_TIMER register data timeout in card bus clock periods */
116#define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */ 113#define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */
117#define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */ 114#define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */
118 115
@@ -146,17 +143,7 @@ static unsigned char *uncached_buffer = AS3525_UNCACHED_ADDR(&aligned_buffer[0])
146 143
147static inline void mci_delay(void) { udelay(1000) ; } 144static inline void mci_delay(void) { udelay(1000) ; }
148 145
149static inline bool card_detect_target(void) 146static void enable_controller(bool on)
150{
151#if defined(HAVE_MULTIDRIVE)
152 return !(GPIOA_PIN(2));
153#else
154 return false;
155#endif
156}
157
158#if defined(HAVE_MULTIDRIVE) || defined(HAVE_HOTSWAP)
159static void enable_controller_mci(bool on)
160{ 147{
161 148
162#if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) 149#if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE)
@@ -210,33 +197,17 @@ static void enable_controller_mci(bool on)
210#endif 197#endif
211 } 198 }
212} 199}
213#endif /* defined(HAVE_MULTIDRIVE) || defined(HAVE_HOTSWAP) */
214 200
215/* AMS v1 have two different drive interfaces MCI_SD(XPD) and GGU_IDE */ 201static inline bool card_detect_target(void)
216static void enable_controller(bool on, const int drive)
217{ 202{
218 203#if defined(HAVE_MULTIDRIVE)
219 if (drive == INTERNAL_AS3525) 204 return !(GPIOA_PIN(2));
220 { 205#else
221#ifndef BOOTLOADER 206 return false;
222 if (on)
223 {
224 bitset32(&CGU_PERI, CGU_NAF_CLOCK_ENABLE);
225 CGU_IDE |= IDE_INTERFACE_CLK; /* interface enable */
226 }
227 else
228 {
229 CGU_IDE &= ~(IDE_INTERFACE_CLK); /* interface disable */
230 bitclr32(&CGU_PERI, CGU_NAF_CLOCK_ENABLE);
231 }
232#endif
233 }
234#if defined(HAVE_MULTIDRIVE) || defined(HAVE_HOTSWAP)
235 else
236 enable_controller_mci(on);
237#endif 207#endif
238} 208}
239 209
210
240#ifdef HAVE_HOTSWAP 211#ifdef HAVE_HOTSWAP
241static int sd1_oneshot_callback(struct timeout *tmo) 212static int sd1_oneshot_callback(struct timeout *tmo)
242{ 213{
@@ -355,7 +326,6 @@ static bool send_cmd(const int drive, const int cmd, const int arg,
355 return false; 326 return false;
356} 327}
357 328
358/* MCI_CLOCK = MCLK / 2x(ClkDiv[bits 7:0]+1) */
359#define MCI_FULLSPEED (MCI_CLOCK_ENABLE | MCI_CLOCK_BYPASS) /* MCLK */ 329#define MCI_FULLSPEED (MCI_CLOCK_ENABLE | MCI_CLOCK_BYPASS) /* MCLK */
360#define MCI_HALFSPEED (MCI_CLOCK_ENABLE) /* MCLK/2 */ 330#define MCI_HALFSPEED (MCI_CLOCK_ENABLE) /* MCLK/2 */
361#define MCI_QUARTERSPEED (MCI_CLOCK_ENABLE | 1) /* MCLK/4 */ 331#define MCI_QUARTERSPEED (MCI_CLOCK_ENABLE | 1) /* MCLK/4 */
@@ -375,7 +345,7 @@ static int sd_init_card(const int drive)
375 /* 100 - 400kHz clock required for Identification Mode */ 345 /* 100 - 400kHz clock required for Identification Mode */
376 /* Start of Card Identification Mode ************************************/ 346 /* Start of Card Identification Mode ************************************/
377 347
378 /* CMD0 Go Idle -- all card functions switch back to default */ 348 /* CMD0 Go Idle */
379 if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) 349 if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL))
380 return -1; 350 return -1;
381 mci_delay(); 351 mci_delay();
@@ -423,10 +393,10 @@ static int sd_init_card(const int drive)
423 393
424 if(sd_wait_for_tran_state(drive)) 394 if(sd_wait_for_tran_state(drive))
425 return -6; 395 return -6;
426 /* CMD6 0xf indicates no influence, [3:0],0x1 - HS Access*/ 396 /* CMD6 */
427 if(!send_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL)) 397 if(!send_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL))
428 return -7; 398 return -7;
429 sleep(HZ/10);/* need to wait at least 8 clock periods */ 399 sleep(HZ/10);
430 400
431 /* go back to STBY state so we can read csd */ 401 /* go back to STBY state so we can read csd */
432 /* CMD7 w/rca=0: Deselect card to put it in STBY state */ 402 /* CMD7 w/rca=0: Deselect card to put it in STBY state */
@@ -547,7 +517,7 @@ static void init_pl180_controller(const int drive)
547int sd_init(void) 517int sd_init(void)
548{ 518{
549 int ret; 519 int ret;
550 CGU_IDE = IDE_INTERFACE_CLK /* enable interface */ 520 CGU_IDE = (1<<6) /* enable non AHB interface*/
551 | (AS3525_IDE_DIV << 2) 521 | (AS3525_IDE_DIV << 2)
552 | AS3525_CLK_PLLA; /* clock source = PLLA */ 522 | AS3525_CLK_PLLA; /* clock source = PLLA */
553 523
@@ -570,9 +540,7 @@ int sd_init(void)
570 /* init mutex */ 540 /* init mutex */
571 mutex_init(&sd_mtx); 541 mutex_init(&sd_mtx);
572 542
573 for (int i = 0; i < NUM_DRIVES ; i++) 543 enable_controller(false);
574 enable_controller(false, i);
575
576 return 0; 544 return 0;
577} 545}
578 546
@@ -688,7 +656,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start,
688 unsigned long response; 656 unsigned long response;
689 bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); 657 bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1));
690 658
691 enable_controller(true, drive); 659 enable_controller(true);
692 led(true); 660 led(true);
693 661
694 if (card_info[drive].initialized <= 0) 662 if (card_info[drive].initialized <= 0)
@@ -724,21 +692,27 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start,
724 else 692 else
725 discard_dcache_range(buf, count * SECTOR_SIZE); 693 discard_dcache_range(buf, count * SECTOR_SIZE);
726 } 694 }
727 const int cmd = write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; 695
728 while(count > 0) 696 while(count)
729 { 697 {
730 /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH 698 /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH
731 * register, so we have to transfer maximum 127 sectors at a time. */ 699 * register, so we have to transfer maximum 127 sectors at a time. */
732 unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */ 700 unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */
733 void *dma_buf; 701 void *dma_buf;
734 702 const int cmd =
703 write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK;
735 unsigned long bank_start = start; 704 unsigned long bank_start = start;
705 unsigned long status;
736 706
737 /* Only switch banks for internal storage */ 707 /* Only switch banks for internal storage */
738 if(drive == INTERNAL_AS3525) 708 if(drive == INTERNAL_AS3525)
739 { 709 {
740 unsigned int bank = bank_start / BLOCKS_PER_BANK; 710 unsigned int bank = 0;
741 bank_start -= bank * BLOCKS_PER_BANK; 711 while(bank_start >= BLOCKS_PER_BANK)
712 {
713 bank_start -= BLOCKS_PER_BANK;
714 bank++;
715 }
742 716
743 /* Switch bank if needed */ 717 /* Switch bank if needed */
744 if(card_info[INTERNAL_AS3525].current_bank != bank) 718 if(card_info[INTERNAL_AS3525].current_bank != bank)
@@ -796,7 +770,10 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start,
796 /*Small delay for writes prevents data crc failures at lower freqs*/ 770 /*Small delay for writes prevents data crc failures at lower freqs*/
797#ifdef HAVE_MULTIDRIVE 771#ifdef HAVE_MULTIDRIVE
798 if((drive == SD_SLOT_AS3525) && !hs_card) 772 if((drive == SD_SLOT_AS3525) && !hs_card)
799 udelay(4); 773 {
774 int write_delay = 125;
775 while(write_delay--);
776 }
800#endif 777#endif
801 } 778 }
802 else 779 else
@@ -827,7 +804,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start,
827 804
828 last_disk_activity = current_tick; 805 last_disk_activity = current_tick;
829 806
830 if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP, &response)) 807 if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP, &status))
831 { 808 {
832 ret = -4*20; 809 ret = -4*20;
833 goto sd_transfer_error; 810 goto sd_transfer_error;
@@ -854,7 +831,7 @@ sd_transfer_error:
854sd_transfer_error_nodma: 831sd_transfer_error_nodma:
855 832
856 led(false); 833 led(false);
857 enable_controller(false, drive); 834 enable_controller(false);
858 835
859 if (ret) /* error */ 836 if (ret) /* error */
860 card_info[drive].initialized = 0; 837 card_info[drive].initialized = 0;
@@ -945,18 +922,12 @@ void ams_sd_get_debug_info(struct ams_sd_debug_info *info)
945 #define MCI_SD *((volatile unsigned long *)(SD_MCI_BASE + 0x04)) 922 #define MCI_SD *((volatile unsigned long *)(SD_MCI_BASE + 0x04))
946 923
947 mutex_lock(&sd_mtx); 924 mutex_lock(&sd_mtx);
948 925 enable_controller(true); /* must be on to read regs */
949 for (int i = 0; i < NUM_DRIVES ; i++)
950 enable_controller(true, i); /* must be on to read regs */
951
952 info->mci_nand = MCI_NAND; 926 info->mci_nand = MCI_NAND;
953#ifdef HAVE_MULTIDRIVE 927#ifdef HAVE_MULTIDRIVE
954 info->mci_sd = MCI_SD; 928 info->mci_sd = MCI_SD;
955#endif 929#endif
956 930 enable_controller(false);
957 for (int i = 0; i < NUM_DRIVES ; i++)
958 enable_controller(false, i);
959
960 mutex_unlock(&sd_mtx); 931 mutex_unlock(&sd_mtx);
961} 932}
962 933
@@ -977,10 +948,10 @@ int sd_event(long id, intptr_t data)
977 948
978 if (id == SYS_HOTSWAP_INSERTED) 949 if (id == SYS_HOTSWAP_INSERTED)
979 { 950 {
980 enable_controller(true, data); 951 enable_controller(true);
981 init_pl180_controller(data); 952 init_pl180_controller(data);
982 rc = sd_init_card(data); 953 rc = sd_init_card(data);
983 enable_controller(false, data); 954 enable_controller(false);
984 } 955 }
985 956
986 mutex_unlock(&sd_mtx); 957 mutex_unlock(&sd_mtx);
@@ -997,42 +968,3 @@ int sd_event(long id, intptr_t data)
997 968
998 return rc; 969 return rc;
999} 970}
1000
1001#if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_DISK)
1002/* declared in system-as3525.c */
1003void ams_sd_set_low_speed(bool slow)
1004{
1005 /* block access while speed is changed */
1006 mutex_lock(&sd_mtx);
1007 enable_controller(true, INTERNAL_AS3525);
1008
1009 /* After a data write, data cannot be written to MCI_CLOCK
1010 for 3 MCLK periods + 2 PCLK periods. ~10us worst case
1011 */
1012 udelay(100);
1013 if (slow)
1014 {
1015 /* only affects internal drive clock speed*/
1016 CGU_IDE = (CGU_IDE & ~(0xF << 2)) | (AS3525_IDE_DIV_MAX << 2);
1017 /* power save is enabled for the sd card(s) */
1018 for (int i = 0; i < NUM_DRIVES ; i++)
1019 {
1020 if (i != INTERNAL_AS3525 && (MCI_CLOCK(i) & MCI_CLOCK_POWERSAVE) == 0)
1021 MCI_CLOCK(i) |= MCI_CLOCK_POWERSAVE;
1022 }
1023 }
1024 else
1025 {
1026 /* Full Speed */
1027 CGU_IDE = (CGU_IDE & ~(0xF << 2)) | (AS3525_IDE_DIV << 2);
1028 for (int i = 0; i < NUM_DRIVES ; i++)
1029 {
1030 if (i != INTERNAL_AS3525 && (MCI_CLOCK(i) & MCI_CLOCK_POWERSAVE) != 0)
1031 MCI_CLOCK(i) = (MCI_CLOCK(i) & ~MCI_CLOCK_POWERSAVE);
1032 }
1033 }
1034 enable_controller(false, INTERNAL_AS3525);
1035 mutex_unlock(&sd_mtx);
1036}
1037#endif
1038
diff --git a/firmware/target/arm/as3525/sd-as3525v2.c b/firmware/target/arm/as3525/sd-as3525v2.c
index d27df5289c..b512cc2ea4 100644
--- a/firmware/target/arm/as3525/sd-as3525v2.c
+++ b/firmware/target/arm/as3525/sd-as3525v2.c
@@ -488,7 +488,7 @@ static int sd_init_card(const int drive)
488 card_info[drive].initialized = 0; 488 card_info[drive].initialized = 0;
489 card_info[drive].rca = 0; 489 card_info[drive].rca = 0;
490 490
491 /* assume 24 MHz clock / (2x)60 = 200 kHz */ 491 /* assume 24 MHz clock / 60 = 400 kHz */
492 MCI_CLKDIV = (MCI_CLKDIV & ~(0xFF)) | 0x3C; /* CLK_DIV_0 : bits 7:0 */ 492 MCI_CLKDIV = (MCI_CLKDIV & ~(0xFF)) | 0x3C; /* CLK_DIV_0 : bits 7:0 */
493 493
494 /* 100 - 400kHz clock required for Identification Mode */ 494 /* 100 - 400kHz clock required for Identification Mode */
@@ -957,27 +957,3 @@ int sd_event(long id, intptr_t data)
957 957
958 return rc; 958 return rc;
959} 959}
960
961#if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_DISK)
962/* declared in system-as3525.c */
963void ams_sd_set_low_speed(bool slow)
964{
965 /* block access while speed is changed */
966 mutex_lock(&sd_mtx);
967 enable_controller(true);
968 if (slow)
969 {
970 CGU_SDSLOT = (CGU_SDSLOT & ~(0xF << 2)) | (AS3525_SDSLOT_DIV_MAX << 2);
971 /* power save is enabled for the sd card(s) ASSUMES CRD0 is int drive! */
972 MCI_CLKENA |= (CCLK_LP_CRD1 | CCLK_LP_CRD2 | CCLK_LP_CRD3);
973 }
974 else
975 {
976 /* Full Speed */
977 CGU_SDSLOT = (CGU_SDSLOT & ~(0xF << 2)) | (AS3525_SDSLOT_DIV << 2);
978 MCI_CLKENA = (MCI_CLKENA & ~(CCLK_LP_CRD1 | CCLK_LP_CRD2 | CCLK_LP_CRD3));
979 }
980 enable_controller(false);
981 mutex_unlock(&sd_mtx);
982}
983#endif
diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c
index 2cd9145567..83ccb55f79 100644
--- a/firmware/target/arm/as3525/system-as3525.c
+++ b/firmware/target/arm/as3525/system-as3525.c
@@ -52,29 +52,6 @@ struct mutex cpufreq_mtx;
52#define default_interrupt(name) \ 52#define default_interrupt(name) \
53 extern __attribute__((weak,alias("UIRQ"))) void name (void) 53 extern __attribute__((weak,alias("UIRQ"))) void name (void)
54 54
55#ifdef CONFIG_POWER_SAVING
56/* Powersave functions either manipulate the system directly
57 or pass enabled flag on to these specific functions
58 dis/enabling powersaving for the selected subsystem
59*/
60#if (CONFIG_POWER_SAVING & POWERSV_CPU)
61/*cpu_set_powersave*/
62#include "settings.h"
63#endif
64#if (CONFIG_POWER_SAVING & POWERSV_DISP)
65/*disp_set_powersave*/
66void ams_ssp_set_low_speed(bool slow); /*lcd-clip-plus.c & lcd-clipzip.c*/
67#endif
68#if (CONFIG_POWER_SAVING & POWERSV_DISK)
69/*disk_set_powersave*/
70void ams_sd_set_low_speed(bool slow); /* sd-as3525.c & sd-as3525v2.c */
71#endif
72#if (CONFIG_POWER_SAVING & POWERSV_I2C)
73/*i2c_set_powersave*/
74void ams_i2c_set_low_speed(bool slow); /* ascodec-as3525.c*/
75#endif
76#endif /*CONFIG_POWER_SAVING*/
77
78#if CONFIG_USBOTG != USBOTG_DESIGNWARE 55#if CONFIG_USBOTG != USBOTG_DESIGNWARE
79static void UIRQ (void) __attribute__((interrupt ("IRQ"))); 56static void UIRQ (void) __attribute__((interrupt ("IRQ")));
80#endif 57#endif
@@ -445,39 +422,6 @@ void udelay(unsigned usecs)
445 ); 422 );
446} 423}
447 424
448#ifdef CONFIG_POWER_SAVING
449#if (CONFIG_POWER_SAVING & POWERSV_CPU)
450void cpu_set_powersave(bool enabled)
451{
452 /*global_settings.cpu_powersave*/
453 /*handled in: set_cpu_frequency()*/
454 (void) enabled;
455}
456#endif
457#if (CONFIG_POWER_SAVING & POWERSV_DISK)
458void disk_set_powersave(bool enabled)
459{
460 /*global_settings.disk_powersave*/
461 ams_sd_set_low_speed(enabled);
462}
463#endif
464#if (CONFIG_POWER_SAVING & POWERSV_DISP)
465void disp_set_powersave(bool enabled)
466{
467 /*global_settings.disp_powersave*/
468 ams_ssp_set_low_speed(enabled);
469}
470#endif
471#if (CONFIG_POWER_SAVING & POWERSV_I2C)
472void i2c_set_powersave(bool enabled)
473{
474 /*global_settings.i2c_powersave*/
475 ams_i2c_set_low_speed(enabled);
476}
477#endif
478#endif /*defined(CONFIG_POWER_SAVING)*/
479
480
481#ifndef BOOTLOADER 425#ifndef BOOTLOADER
482#ifdef HAVE_ADJUSTABLE_CPU_FREQ 426#ifdef HAVE_ADJUSTABLE_CPU_FREQ
483bool set_cpu_frequency__lock(void) 427bool set_cpu_frequency__lock(void)
@@ -537,12 +481,7 @@ void set_cpu_frequency(long frequency)
537 CGU_PROC = ((0xf << 4) | (0x3 << 2) | AS3525_CLK_MAIN); 481 CGU_PROC = ((0xf << 4) | (0x3 << 2) | AS3525_CLK_MAIN);
538 482
539#ifdef HAVE_ADJUSTABLE_CPU_VOLTAGE 483#ifdef HAVE_ADJUSTABLE_CPU_VOLTAGE
540 /* Decreasing frequency so reduce voltage after change */ 484 /* Decreasing frequency so reduce voltage after change */
541#if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_CPU)
542 if (!global_settings.cpu_powersave)
543 ascodec_write(AS3514_CVDD_DCDC3, (AS314_CP_DCDC3_SETTING | CVDD_1_15));
544 else
545#endif
546 ascodec_write(AS3514_CVDD_DCDC3, (AS314_CP_DCDC3_SETTING | CVDD_1_10)); 485 ascodec_write(AS3514_CVDD_DCDC3, (AS314_CP_DCDC3_SETTING | CVDD_1_10));
547#endif /* HAVE_ADJUSTABLE_CPU_VOLTAGE */ 486#endif /* HAVE_ADJUSTABLE_CPU_VOLTAGE */
548 487
@@ -580,13 +519,6 @@ void set_cpu_frequency(long frequency)
580 519
581 /* Set CVDD1 power supply */ 520 /* Set CVDD1 power supply */
582#ifdef HAVE_ADJUSTABLE_CPU_VOLTAGE 521#ifdef HAVE_ADJUSTABLE_CPU_VOLTAGE
583#if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_CPU)
584 if (!global_settings.cpu_powersave)
585 {
586 ascodec_write_pmu(0x17, 1, 0x80 | 26);
587 return;
588 }
589#endif
590#if defined(SANSA_CLIPZIP) 522#if defined(SANSA_CLIPZIP)
591 ascodec_write_pmu(0x17, 1, 0x80 | 20); 523 ascodec_write_pmu(0x17, 1, 0x80 | 20);
592#elif defined(SANSA_CLIPPLUS) 524#elif defined(SANSA_CLIPPLUS)
diff --git a/firmware/target/arm/as3525/system-target.h b/firmware/target/arm/as3525/system-target.h
index 9c5b5a9cd6..5cdc573a1b 100644
--- a/firmware/target/arm/as3525/system-target.h
+++ b/firmware/target/arm/as3525/system-target.h
@@ -73,26 +73,6 @@ static inline void mdelay(unsigned msecs)
73void usb_insert_int(void); 73void usb_insert_int(void);
74void usb_remove_int(void); 74void usb_remove_int(void);
75 75
76
77#ifdef CONFIG_POWER_SAVING
78/* Powersave functions either manipulate the system directly
79 or pass enabled flag on to the devices specific function
80 dis/enabling powersaving for the selected subsystem
81*/
82#if (CONFIG_POWER_SAVING & POWERSV_CPU)
83void cpu_set_powersave(bool enabled);
84#endif
85#if (CONFIG_POWER_SAVING & POWERSV_DISP)
86void disp_set_powersave(bool enabled);
87#endif
88#if (CONFIG_POWER_SAVING & POWERSV_DISK)
89void disk_set_powersave(bool enabled);
90#endif
91#if (CONFIG_POWER_SAVING & POWERSV_I2C)
92void i2c_set_powersave(bool enabled);
93#endif
94#endif /*CONFIG_POWER_SAVING*/
95
96#ifdef HAVE_ADJUSTABLE_CPU_FREQ 76#ifdef HAVE_ADJUSTABLE_CPU_FREQ
97#define CPU_BOOST_LOCK_DEFINED 77#define CPU_BOOST_LOCK_DEFINED
98 78