Commit second part of FS#9663 by Thomas Martitz. Enable button light on fuze and...
[kugel-rb.git] / firmware / target / arm / as3525 / ata_sd_as3525.c
blob44fe3e4314e6f7a549567b7e781314c4c32a1a1d
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 Daniel Ankers
11 * Copyright © 2008 Rafaël Carré
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
23 /* Driver for the ARM PL180 SD/MMC controller inside AS3525 SoC */
25 #include "config.h" /* for HAVE_MULTIVOLUME */
26 #include "fat.h"
27 #include "thread.h"
28 #include "hotswap.h"
29 #include "system.h"
30 #include "cpu.h"
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include "as3525.h"
35 #include "pl180.h" /* SD controller */
36 #include "pl081.h" /* DMA controller */
37 #include "dma-target.h" /* DMA request lines */
38 #include "clock-target.h"
39 #include "panic.h"
40 #include "stdbool.h"
41 #include "ata_idle_notify.h"
42 #include "sd.h"
44 #ifdef HAVE_HOTSWAP
45 #include "disk.h"
46 #endif
48 /* command flags */
49 #define MCI_NO_FLAGS (0<<0)
50 #define MCI_RESP (1<<0)
51 #define MCI_LONG_RESP (1<<1)
52 #define MCI_ARG (1<<2)
54 /* ARM PL180 registers */
55 #define MCI_POWER(i) (*(volatile unsigned char *) (pl180_base[i]+0x00))
56 #define MCI_CLOCK(i) (*(volatile unsigned long *) (pl180_base[i]+0x04))
57 #define MCI_ARGUMENT(i) (*(volatile unsigned long *) (pl180_base[i]+0x08))
58 #define MCI_COMMAND(i) (*(volatile unsigned long *) (pl180_base[i]+0x0C))
59 #define MCI_RESPCMD(i) (*(volatile unsigned long *) (pl180_base[i]+0x10))
60 #define MCI_RESP0(i) (*(volatile unsigned long *) (pl180_base[i]+0x14))
61 #define MCI_RESP1(i) (*(volatile unsigned long *) (pl180_base[i]+0x18))
62 #define MCI_RESP2(i) (*(volatile unsigned long *) (pl180_base[i]+0x1C))
63 #define MCI_RESP3(i) (*(volatile unsigned long *) (pl180_base[i]+0x20))
64 #define MCI_DATA_TIMER(i) (*(volatile unsigned long *) (pl180_base[i]+0x24))
65 #define MCI_DATA_LENGTH(i) (*(volatile unsigned short*) (pl180_base[i]+0x28))
66 #define MCI_DATA_CTRL(i) (*(volatile unsigned char *) (pl180_base[i]+0x2C))
67 #define MCI_DATA_CNT(i) (*(volatile unsigned short*) (pl180_base[i]+0x30))
68 #define MCI_STATUS(i) (*(volatile unsigned long *) (pl180_base[i]+0x34))
69 #define MCI_CLEAR(i) (*(volatile unsigned long *) (pl180_base[i]+0x38))
70 #define MCI_MASK0(i) (*(volatile unsigned long *) (pl180_base[i]+0x3C))
71 #define MCI_MASK1(i) (*(volatile unsigned long *) (pl180_base[i]+0x40))
72 #define MCI_SELECT(i) (*(volatile unsigned long *) (pl180_base[i]+0x44))
73 #define MCI_FIFO_CNT(i) (*(volatile unsigned long *) (pl180_base[i]+0x48))
75 #define MCI_ERROR \
76 (MCI_DATA_CRC_FAIL | MCI_DATA_TIMEOUT | MCI_RX_OVERRUN | MCI_TX_UNDERRUN)
78 #define MCI_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80))
79 /* volumes */
80 #define INTERNAL_AS3525 0 /* embedded SD card */
81 #define SD_SLOT_AS3525 1 /* SD slot if present */
83 static const int pl180_base[NUM_VOLUMES] = {
84 NAND_FLASH_BASE
85 #ifdef HAVE_MULTIVOLUME
86 , SD_MCI_BASE
87 #endif
90 static int sd_init_card(const int drive);
91 static void init_pl180_controller(const int drive);
92 /* TODO : BLOCK_SIZE != SECTOR_SIZE ? */
93 #define BLOCK_SIZE 512
94 #define SECTOR_SIZE 512
96 static tSDCardInfo card_info[NUM_VOLUMES];
98 /* for compatibility */
99 static long last_disk_activity = -1;
101 #define MIN_YIELD_PERIOD 5 /* ticks */
102 static long next_yield = 0;
104 static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
105 static const char sd_thread_name[] = "ata/sd";
106 static struct mutex sd_mtx SHAREDBSS_ATTR;
107 static struct event_queue sd_queue;
108 #ifndef BOOTLOADER
109 static bool sd_enabled = false;
110 #endif
112 static struct wakeup transfer_completion_signal;
113 static volatile bool retry;
115 static inline void mci_delay(void) { int i = 0xffff; while(i--) ; }
117 static void mci_set_clock_divider(const int drive, int divider)
119 int clock = MCI_CLOCK(drive);
121 if(divider > 1)
123 /* use divide logic */
124 clock &= ~MCI_CLOCK_BYPASS;
126 /* convert divider to MCI_CLOCK logic */
127 divider = (divider/2) - 1;
128 if(divider >= 256)
129 divider = 255;
131 else
133 /* bypass dividing logic */
134 clock |= MCI_CLOCK_BYPASS;
135 divider = 0;
138 MCI_CLOCK(drive) = clock | divider;
140 mci_delay();
143 #ifdef HAVE_HOTSWAP
144 #if defined(SANSA_E200V2) || defined(SANSA_FUZE)
145 static bool sd1_oneshot_callback(struct timeout *tmo)
147 (void)tmo;
149 /* This is called only if the state was stable for 300ms - check state
150 * and post appropriate event. */
151 if (card_detect_target())
153 queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
155 else
156 queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
158 return false;
161 void INT_GPIOA(void)
163 static struct timeout sd1_oneshot;
164 /* reset irq */
165 GPIOA_IC = (1<<2);
166 timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0);
168 #endif
169 #endif
171 void INT_NAND(void)
173 const int status = MCI_STATUS(INTERNAL_AS3525);
175 if(status & MCI_ERROR)
176 retry = true;
178 wakeup_signal(&transfer_completion_signal);
179 MCI_CLEAR(INTERNAL_AS3525) = status;
182 #ifdef HAVE_MULTIVOLUME
183 void INT_MCI0(void)
185 const int status = MCI_STATUS(SD_SLOT_AS3525);
187 if(status & MCI_ERROR)
188 retry = true;
190 wakeup_signal(&transfer_completion_signal);
191 MCI_CLEAR(SD_SLOT_AS3525) = status;
193 #endif
195 static bool send_cmd(const int drive, const int cmd, const int arg,
196 const int flags, int *response)
198 int val, status;
200 while(MCI_STATUS(drive) & MCI_CMD_ACTIVE);
202 if(MCI_COMMAND(drive) & MCI_COMMAND_ENABLE) /* clears existing command */
204 MCI_COMMAND(drive) = 0;
205 mci_delay();
208 val = cmd | MCI_COMMAND_ENABLE;
209 if(flags & MCI_RESP)
211 val |= MCI_COMMAND_RESPONSE;
212 if(flags & MCI_LONG_RESP)
213 val |= MCI_COMMAND_LONG_RESPONSE;
216 MCI_CLEAR(drive) = 0x7ff;
218 MCI_ARGUMENT(drive) = (flags & MCI_ARG) ? arg : 0;
219 MCI_COMMAND(drive) = val;
221 while(MCI_STATUS(drive) & MCI_CMD_ACTIVE); /* wait for cmd completion */
223 MCI_COMMAND(drive) = 0;
224 MCI_ARGUMENT(drive) = ~0;
226 status = MCI_STATUS(drive);
227 MCI_CLEAR(drive) = 0x7ff;
229 if(flags & MCI_RESP)
231 if(status & MCI_CMD_TIMEOUT)
232 return false;
233 else if(status & (MCI_CMD_CRC_FAIL /* FIXME? */ | MCI_CMD_RESP_END))
234 { /* resp received */
235 if(flags & MCI_LONG_RESP)
237 /* store the response in little endian order for the words */
238 response[0] = MCI_RESP3(drive);
239 response[1] = MCI_RESP2(drive);
240 response[2] = MCI_RESP1(drive);
241 response[3] = MCI_RESP0(drive);
243 else
244 response[0] = MCI_RESP0(drive);
245 return true;
248 else if(status & MCI_CMD_SENT)
249 return true;
251 return false;
254 static int sd_init_card(const int drive)
256 unsigned int c_size;
257 unsigned long c_mult;
258 int response;
259 int max_tries = 100; /* max acmd41 attemps */
260 bool sdhc;
262 if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_FLAGS, NULL))
263 return -1;
265 mci_delay();
267 sdhc = false;
268 if(send_cmd(drive, SD_SEND_IF_COND, 0x1AA, MCI_RESP|MCI_ARG, &response))
269 if((response & 0xFFF) == 0x1AA)
270 sdhc = true;
272 do {
273 /* some MicroSD cards seems to need more delays, so play safe */
274 mci_delay();
275 mci_delay();
276 mci_delay();
278 /* app_cmd */
279 if( !send_cmd(drive, SD_APP_CMD, 0, MCI_RESP|MCI_ARG, &response) ||
280 !(response & (1<<5)) )
282 return -2;
285 /* acmd41 */
286 if(!send_cmd(drive, SD_APP_OP_COND, (sdhc ? 0x40FF8000 : (1<<23)),
287 MCI_RESP|MCI_ARG, &card_info[drive].ocr))
288 return -3;
290 } while(!(card_info[drive].ocr & (1<<31)) && max_tries--);
292 if(max_tries < 0)
293 return -4;
295 /* send CID */
296 if(!send_cmd(drive, SD_ALL_SEND_CID, 0, MCI_RESP|MCI_LONG_RESP|MCI_ARG,
297 card_info[drive].cid))
298 return -5;
300 /* send RCA */
301 if(!send_cmd(drive, SD_SEND_RELATIVE_ADDR, 0, MCI_RESP|MCI_ARG,
302 &card_info[drive].rca))
303 return -6;
305 /* send CSD */
306 if(!send_cmd(drive, SD_SEND_CSD, card_info[drive].rca,
307 MCI_RESP|MCI_LONG_RESP|MCI_ARG, card_info[drive].csd))
308 return -7;
310 /* These calculations come from the Sandisk SD card product manual */
311 if( (card_info[drive].csd[3]>>30) == 0)
313 /* CSD version 1.0 */
314 c_size = ((card_info[drive].csd[2] & 0x3ff) << 2) + (card_info[drive].csd[1]>>30) + 1;
315 c_mult = 4 << ((card_info[drive].csd[1] >> 15) & 7);
316 card_info[drive].max_read_bl_len = 1 << ((card_info[drive].csd[2] >> 16) & 15);
317 card_info[drive].block_size = BLOCK_SIZE; /* Always use 512 byte blocks */
318 card_info[drive].numblocks = c_size * c_mult * (card_info[drive].max_read_bl_len/512);
319 card_info[drive].capacity = card_info[drive].numblocks * card_info[drive].block_size;
321 #ifdef HAVE_MULTIVOLUME
322 else if( (card_info[drive].csd[3]>>30) == 1)
324 /* CSD version 2.0 */
325 c_size = ((card_info[drive].csd[2] & 0x3f) << 16) + (card_info[drive].csd[1]>>16) + 1;
326 card_info[drive].max_read_bl_len = 1 << ((card_info[drive].csd[2] >> 16) & 0xf);
327 card_info[drive].block_size = BLOCK_SIZE; /* Always use 512 byte blocks */
328 card_info[drive].numblocks = c_size << 10;
329 card_info[drive].capacity = card_info[drive].numblocks * card_info[drive].block_size;
331 #endif
333 if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_ARG, NULL))
334 return -9;
336 if(!send_cmd(drive, SD_APP_CMD, card_info[drive].rca, MCI_ARG, NULL))
337 return -10;
339 if(!send_cmd(drive, SD_SET_BUS_WIDTH, card_info[drive].rca | 2, MCI_ARG, NULL))
340 return -11;
342 if(!send_cmd(drive, SD_SET_BLOCKLEN, card_info[drive].block_size, MCI_ARG,
343 NULL))
344 return -12;
346 card_info[drive].initialized = 1;
348 mci_set_clock_divider(drive, 1); /* full speed */
350 return 0;
353 static void sd_thread(void) __attribute__((noreturn));
354 static void sd_thread(void)
356 struct queue_event ev;
357 bool idle_notified = false;
359 while (1)
361 queue_wait_w_tmo(&sd_queue, &ev, HZ);
363 switch ( ev.id )
365 #ifdef HAVE_HOTSWAP
366 case SYS_HOTSWAP_INSERTED:
367 case SYS_HOTSWAP_EXTRACTED:
368 fat_lock(); /* lock-out FAT activity first -
369 prevent deadlocking via disk_mount that
370 would cause a reverse-order attempt with
371 another thread */
372 mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
373 into driver that bypass the fat cache */
375 /* We now have exclusive control of fat cache and ata */
377 disk_unmount(SD_SLOT_AS3525); /* release "by force", ensure file
378 descriptors aren't leaked and any busy
379 ones are invalid if mounting */
381 /* Force card init for new card, re-init for re-inserted one or
382 * clear if the last attempt to init failed with an error. */
383 card_info[SD_SLOT_AS3525].initialized = 0;
385 if (ev.id == SYS_HOTSWAP_INSERTED)
387 sd_enable(true);
388 init_pl180_controller(SD_SLOT_AS3525);
389 sd_init_card(SD_SLOT_AS3525);
390 disk_mount(SD_SLOT_AS3525);
393 queue_broadcast(SYS_FS_CHANGED, 0);
395 /* Access is now safe */
396 mutex_unlock(&sd_mtx);
397 fat_unlock();
398 sd_enable(false);
399 break;
400 #endif
401 case SYS_TIMEOUT:
402 if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
404 idle_notified = false;
406 else
408 /* never let a timer wrap confuse us */
409 next_yield = current_tick;
411 if (!idle_notified)
413 call_storage_idle_notifys(false);
414 idle_notified = true;
417 break;
418 #if 0
419 case SYS_USB_CONNECTED:
420 usb_acknowledge(SYS_USB_CONNECTED_ACK);
421 /* Wait until the USB cable is extracted again */
422 usb_wait_for_disconnect(&sd_queue);
424 break;
425 case SYS_USB_DISCONNECTED:
426 usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
427 break;
428 #endif
433 static void init_pl180_controller(const int drive)
435 MCI_COMMAND(drive) = MCI_DATA_CTRL(drive) = 0;
436 MCI_CLEAR(drive) = 0x7ff;
438 MCI_MASK0(drive) = MCI_MASK1(drive) = MCI_ERROR | MCI_DATA_END;
440 #ifdef HAVE_MULTIVOLUME
441 VIC_INT_ENABLE |=
442 (drive == INTERNAL_AS3525) ? INTERRUPT_NAND : INTERRUPT_MCI0;
444 #if defined(SANSA_E200V2) || defined(SANSA_FUZE)
445 /* setup isr for microsd monitoring */
446 VIC_INT_ENABLE |= (INTERRUPT_GPIOA);
447 /* clear previous irq */
448 GPIOA_IC |= (1<<2);
449 /* enable edge detecting */
450 GPIOA_IS &= ~(1<<2);
451 /* detect both raising and falling edges */
452 GPIOA_IBE |= (1<<2);
454 #endif
456 #else
457 VIC_INT_ENABLE |= INTERRUPT_NAND;
458 #endif
460 MCI_POWER(drive) = MCI_POWER_UP|(10 /*voltage*/ << 2); /* use OF voltage */
461 mci_delay();
463 MCI_POWER(drive) |= MCI_POWER_ON;
464 mci_delay();
466 MCI_SELECT(drive) = 0;
468 MCI_CLOCK(drive) = MCI_CLOCK_ENABLE;
469 MCI_CLOCK(drive) &= ~MCI_CLOCK_POWERSAVE;
471 /* set MCLK divider */
472 mci_set_clock_divider(drive,
473 CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ));
476 int sd_init(void)
478 int ret;
479 CGU_IDE = (1<<7) /* AHB interface enable */ |
480 (1<<6) /* interface enable */ |
481 ((CLK_DIV(AS3525_PLLA_FREQ, AS3525_IDE_FREQ) - 1) << 2) |
482 1; /* clock source = PLLA */
485 CGU_PERI |= CGU_NAF_CLOCK_ENABLE;
486 #ifdef HAVE_MULTIVOLUME
487 CGU_PERI |= CGU_MCI_CLOCK_ENABLE;
488 CCU_IO &= ~(1<<3); /* bits 3:2 = 01, xpd is SD interface */
489 CCU_IO |= (1<<2);
490 #endif
492 wakeup_init(&transfer_completion_signal);
494 init_pl180_controller(INTERNAL_AS3525);
495 ret = sd_init_card(INTERNAL_AS3525);
496 if(ret < 0)
497 return ret;
498 #ifdef HAVE_MULTIVOLUME
499 init_pl180_controller(SD_SLOT_AS3525);
500 #endif
502 /* init mutex */
503 mutex_init(&sd_mtx);
505 queue_init(&sd_queue, true);
506 create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
507 sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
509 #ifndef BOOTLOADER
510 sd_enabled = true;
511 sd_enable(false);
512 #endif
513 return 0;
516 #ifdef STORAGE_GET_INFO
517 void sd_get_info(IF_MV2(int drive,) struct storage_info *info)
519 #ifndef HAVE_MULTIVOLUME
520 const int drive=0;
521 #endif
522 info->sector_size=card_info[drive].block_size;
523 info->num_sectors=card_info[drive].numblocks;
524 info->vendor="Rockbox";
525 info->product = (drive == 0) ? "Internal Storage" : "SD Card Slot";
526 info->revision="0.00";
528 #endif
530 #ifdef HAVE_HOTSWAP
531 bool sd_removable(IF_MV_NONVOID(int drive))
533 #ifndef HAVE_MULTIVOLUME
534 const int drive=0;
535 #endif
536 return (drive==1);
539 bool sd_present(IF_MV_NONVOID(int drive))
541 #ifndef HAVE_MULTIVOLUME
542 const int drive=0;
543 #endif
544 return (card_info[drive].initialized && card_info[drive].numblocks > 0);
546 #endif
548 static int sd_wait_for_state(const int drive, unsigned int state)
550 unsigned int response = 0;
551 unsigned int timeout = 100; /* ticks */
552 long t = current_tick;
554 while (1)
556 long tick;
558 if(!send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca,
559 MCI_RESP|MCI_ARG, &response))
560 return -1;
562 if (((response >> 9) & 0xf) == state)
563 return 0;
565 if(TIME_AFTER(current_tick, t + timeout))
566 return -1;
568 if (TIME_AFTER((tick = current_tick), next_yield))
570 yield();
571 timeout += current_tick - tick;
572 next_yield = tick + MIN_YIELD_PERIOD;
577 static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
578 int count, void* buf, bool write)
580 #ifndef HAVE_MULTIVOLUME
581 const int drive = 0;
582 #endif
583 int ret = 0;
585 /* skip SanDisk OF */
586 if (drive == INTERNAL_AS3525)
587 #if defined(SANSA_E200V2) || defined(SANSA_FUZE)
588 start += 61440;
589 #else
590 start += 20480;
591 #endif
593 mutex_lock(&sd_mtx);
594 #ifndef BOOTLOADER
595 sd_enable(true);
596 #endif
598 if (card_info[drive].initialized <= 0)
600 ret = sd_init_card(drive);
601 if (!(card_info[drive].initialized))
603 panicf("card not initialised (%d)", ret);
604 goto sd_transfer_error;
608 last_disk_activity = current_tick;
609 ret = sd_wait_for_state(drive, SD_TRAN);
610 if (ret < 0)
612 panicf("wait for state failed on drive %d", drive);
613 goto sd_transfer_error;
616 dma_retain();
618 while(count)
620 /* Interrupt handler might set this to true during transfer */
621 retry = false;
622 /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH
623 * register, so we have to transfer maximum 127 sectors at a time. */
624 unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */
625 const int cmd =
626 write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK;
628 if(card_info[drive].ocr & (1<<30) ) /* SDHC */
629 ret = send_cmd(drive, cmd, start, MCI_ARG, NULL);
630 else
631 ret = send_cmd(drive, cmd, start * BLOCK_SIZE,
632 MCI_ARG, NULL);
634 if (ret < 0)
635 panicf("transfer multiple blocks failed (%d)", ret);
637 if(write)
638 dma_enable_channel(0, buf, MCI_FIFO(drive),
639 (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
640 DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL);
641 else
642 dma_enable_channel(0, MCI_FIFO(drive), buf,
643 (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
644 DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL);
646 MCI_DATA_TIMER(drive) = 0x1000000; /* FIXME: arbitrary */
647 MCI_DATA_LENGTH(drive) = transfer * card_info[drive].block_size;
648 MCI_DATA_CTRL(drive) = (1<<0) /* enable */ |
649 (!write<<1) /* transfer direction */ |
650 (1<<3) /* DMA */ |
651 (9<<4) /* 2^9 = 512 */ ;
654 wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
655 if(!retry)
657 buf += transfer * SECTOR_SIZE;
658 start += transfer;
659 count -= transfer;
662 last_disk_activity = current_tick;
664 if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_NO_FLAGS, NULL))
666 ret = -666;
667 panicf("STOP TRANSMISSION failed");
668 goto sd_transfer_error;
671 ret = sd_wait_for_state(drive, SD_TRAN);
672 if (ret < 0)
674 panicf(" wait for state TRAN failed (%d)", ret);
675 goto sd_transfer_error;
679 dma_release();
681 #ifndef BOOTLOADER
682 sd_enable(false);
683 #endif
684 mutex_unlock(&sd_mtx);
685 return 0;
687 sd_transfer_error:
688 panicf("transfer error : %d",ret);
689 card_info[drive].initialized = 0;
690 return ret;
693 int sd_read_sectors(IF_MV2(int drive,) unsigned long start, int count,
694 void* buf)
696 return sd_transfer_sectors(IF_MV2(drive,) start, count, buf, false);
699 int sd_write_sectors(IF_MV2(int drive,) unsigned long start, int count,
700 const void* buf)
703 #ifdef BOOTLOADER /* we don't need write support in bootloader */
704 #ifdef HAVE_MULTIVOLUME
705 (void) drive;
706 #endif
707 (void) start;
708 (void) count;
709 (void) buf;
710 return -1;
711 #else
712 return sd_transfer_sectors(IF_MV2(drive,) start, count, (void*)buf, true);
713 #endif
716 #ifndef BOOTLOADER
717 void sd_sleep(void)
721 void sd_spin(void)
725 void sd_spindown(int seconds)
727 (void)seconds;
730 long sd_last_disk_activity(void)
732 return last_disk_activity;
735 void sd_enable(bool on)
737 if (sd_enabled == on)
738 return; /* nothing to do */
739 if(on)
741 CGU_PERI |= CGU_NAF_CLOCK_ENABLE;
742 #ifdef HAVE_MULTIVOLUME
743 CGU_PERI |= CGU_MCI_CLOCK_ENABLE;
744 /* Needed for buttonlight and MicroSD to work at the same time */
745 /* Turn ROD control on, as the OF does */
746 SD_MCI_POWER |= (1<<7);
747 CCU_IO |= (1<<2);
748 #endif
749 CGU_IDE |= (1<<7) /* AHB interface enable */ |
750 (1<<6) /* interface enable */;
751 sd_enabled = true;
753 else
755 CGU_PERI &= ~CGU_NAF_CLOCK_ENABLE;
756 #ifdef HAVE_MULTIVOLUME
757 CGU_PERI &= ~CGU_MCI_CLOCK_ENABLE;
758 /* Needed for buttonlight and MicroSD to work at the same time */
759 /* Turn ROD control off, as the OF does */
760 SD_MCI_POWER &= ~(1<<7);
761 CCU_IO &= ~(1<<2);
762 #endif
763 CGU_IDE &= ~((1<<7)|(1<<6));
764 sd_enabled = false;
768 /* move the sd-card info to mmc struct */
769 tCardInfo *card_get_info_target(int card_no)
771 int i, temp;
772 static tCardInfo card;
773 static const char mantissa[] = { /* *10 */
774 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 };
775 static const int exponent[] = { /* use varies */
776 1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000 };
778 card.initialized = card_info[card_no].initialized;
779 card.ocr = card_info[card_no].ocr;
780 for(i=0; i<4; i++) card.csd[i] = card_info[card_no].csd[i];
781 for(i=0; i<4; i++) card.cid[i] = card_info[card_no].cid[i];
782 card.numblocks = card_info[card_no].numblocks;
783 card.blocksize = card_info[card_no].block_size;
784 temp = card_extract_bits(card.csd, 29, 3);
785 card.speed = mantissa[card_extract_bits(card.csd, 25, 4)]
786 * exponent[temp > 2 ? 7 : temp + 4];
787 card.nsac = 100 * card_extract_bits(card.csd, 16, 8);
788 temp = card_extract_bits(card.csd, 13, 3);
789 card.tsac = mantissa[card_extract_bits(card.csd, 9, 4)]
790 * exponent[temp] / 10;
791 card.cid[0] = htobe32(card.cid[0]); /* ascii chars here */
792 card.cid[1] = htobe32(card.cid[1]); /* ascii chars here */
793 temp = *((char*)card.cid+13); /* adjust year<=>month, 1997 <=> 2000 */
794 *((char*)card.cid+13) = (unsigned char)((temp >> 4) | (temp << 4)) + 3;
796 return &card;
799 bool card_detect_target(void)
801 #ifdef HAVE_HOTSWAP
802 /* TODO: add e200/c200 */
803 #if defined(SANSA_E200V2) || defined(SANSA_FUZE)
804 return !(GPIOA_PIN(2));
805 #endif
806 #endif
807 return false;
810 #ifdef HAVE_HOTSWAP
811 void card_enable_monitoring_target(bool on)
813 if (on)
815 /* add e200v2/c200v2 here */
816 #if defined(SANSA_E200V2) || defined(SANSA_FUZE)
817 /* enable isr*/
818 GPIOA_IE |= (1<<2);
819 #endif
821 else
823 #if defined(SANSA_E200V2) || defined(SANSA_FUZE)
824 /* edisable isr*/
825 GPIOA_IE &= ~(1<<2);
826 #endif
829 #endif
831 #endif /* BOOTLOADER */