diff options
Diffstat (limited to 'firmware/target/arm/rk27xx')
-rw-r--r-- | firmware/target/arm/rk27xx/sd-rk27xx.c | 187 |
1 files changed, 69 insertions, 118 deletions
diff --git a/firmware/target/arm/rk27xx/sd-rk27xx.c b/firmware/target/arm/rk27xx/sd-rk27xx.c index 6eeff7bae5..2ddfd0cf0a 100644 --- a/firmware/target/arm/rk27xx/sd-rk27xx.c +++ b/firmware/target/arm/rk27xx/sd-rk27xx.c | |||
@@ -34,13 +34,7 @@ | |||
34 | #include <string.h> | 34 | #include <string.h> |
35 | #include "panic.h" | 35 | #include "panic.h" |
36 | #include "stdbool.h" | 36 | #include "stdbool.h" |
37 | #include "ata_idle_notify.h" | 37 | #include "storage.h" |
38 | #include "sd.h" | ||
39 | #include "usb.h" | ||
40 | |||
41 | #ifdef HAVE_HOTSWAP | ||
42 | #include "disk.h" | ||
43 | #endif | ||
44 | 38 | ||
45 | #include "lcd.h" | 39 | #include "lcd.h" |
46 | #include <stdarg.h> | 40 | #include <stdarg.h> |
@@ -57,21 +51,39 @@ static tCardInfo card_info; | |||
57 | /* for compatibility */ | 51 | /* for compatibility */ |
58 | static long last_disk_activity = -1; | 52 | static long last_disk_activity = -1; |
59 | 53 | ||
60 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | ||
61 | static unsigned char aligned_buf[512] STORAGE_ALIGN_ATTR; | 54 | static unsigned char aligned_buf[512] STORAGE_ALIGN_ATTR; |
62 | 55 | ||
63 | static const char sd_thread_name[] = "ata/sd"; | ||
64 | static struct mutex sd_mtx SHAREDBSS_ATTR; | 56 | static struct mutex sd_mtx SHAREDBSS_ATTR; |
65 | static struct event_queue sd_queue; | ||
66 | #ifndef BOOTLOADER | 57 | #ifndef BOOTLOADER |
67 | bool sd_enabled = false; | 58 | bool sd_enabled = false; |
68 | #endif | 59 | #endif |
69 | 60 | ||
61 | #ifdef CONFIG_STORAGE_MULTI | ||
62 | static int sd_first_drive = 0; | ||
63 | #else | ||
64 | #define sd_first_drive 0 | ||
65 | #endif | ||
66 | |||
70 | static struct semaphore transfer_completion_signal; | 67 | static struct semaphore transfer_completion_signal; |
71 | static struct semaphore command_completion_signal; | 68 | static struct semaphore command_completion_signal; |
72 | static volatile bool retry; | 69 | static volatile bool retry; |
73 | static volatile int cmd_error; | 70 | static volatile int cmd_error; |
74 | 71 | ||
72 | static void enable_controller(bool on) | ||
73 | { | ||
74 | /* enable or disable clock signal for SD module */ | ||
75 | if (on) | ||
76 | { | ||
77 | SCU_CLKCFG &= ~CLKCFG_SD; | ||
78 | led(true); | ||
79 | } | ||
80 | else | ||
81 | { | ||
82 | SCU_CLKCFG |= CLKCFG_SD; | ||
83 | led(false); | ||
84 | } | ||
85 | } | ||
86 | |||
75 | /* interrupt handler for SD */ | 87 | /* interrupt handler for SD */ |
76 | void INT_SD(void) | 88 | void INT_SD(void) |
77 | { | 89 | { |
@@ -318,81 +330,6 @@ static int sd_init_card(void) | |||
318 | return 0; | 330 | return 0; |
319 | } | 331 | } |
320 | 332 | ||
321 | static void sd_thread(void) NORETURN_ATTR; | ||
322 | static void sd_thread(void) | ||
323 | { | ||
324 | struct queue_event ev; | ||
325 | bool idle_notified = false; | ||
326 | |||
327 | while (1) | ||
328 | { | ||
329 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
330 | |||
331 | switch ( ev.id ) | ||
332 | { | ||
333 | #ifdef HAVE_HOTSWAP | ||
334 | case SYS_HOTSWAP_INSERTED: | ||
335 | case SYS_HOTSWAP_EXTRACTED:; | ||
336 | int success = 1; | ||
337 | |||
338 | disk_unmount(sd_first_drive); /* release "by force" */ | ||
339 | |||
340 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
341 | |||
342 | /* Force card init for new card, re-init for re-inserted one or | ||
343 | * clear if the last attempt to init failed with an error. */ | ||
344 | card_info.initialized = 0; | ||
345 | |||
346 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
347 | { | ||
348 | success = 0; | ||
349 | sd_enable(true); | ||
350 | int rc = sd_init_card(sd_first_drive); | ||
351 | sd_enable(false); | ||
352 | if (rc >= 0) | ||
353 | success = 2; | ||
354 | else /* initialisation failed */ | ||
355 | panicf("microSD init failed : %d", rc); | ||
356 | } | ||
357 | |||
358 | /* Access is now safe */ | ||
359 | mutex_unlock(&sd_mtx); | ||
360 | |||
361 | if (success > 1) | ||
362 | success = disk_mount(sd_first_drive); /* 0 if fail */ | ||
363 | |||
364 | /* | ||
365 | * Mount succeeded, or this was an EXTRACTED event, | ||
366 | * in both cases notify the system about the changed filesystems | ||
367 | */ | ||
368 | if (success) | ||
369 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
370 | |||
371 | break; | ||
372 | #endif /* HAVE_HOTSWAP */ | ||
373 | |||
374 | case SYS_TIMEOUT: | ||
375 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
376 | { | ||
377 | idle_notified = false; | ||
378 | } | ||
379 | else if (!idle_notified) | ||
380 | { | ||
381 | call_storage_idle_notifys(false); | ||
382 | idle_notified = true; | ||
383 | } | ||
384 | break; | ||
385 | |||
386 | case SYS_USB_CONNECTED: | ||
387 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
388 | /* Wait until the USB cable is extracted again */ | ||
389 | usb_wait_for_disconnect(&sd_queue); | ||
390 | |||
391 | break; | ||
392 | } | ||
393 | } | ||
394 | } | ||
395 | |||
396 | static void init_controller(void) | 333 | static void init_controller(void) |
397 | { | 334 | { |
398 | /* reset SD module */ | 335 | /* reset SD module */ |
@@ -441,6 +378,7 @@ int sd_init(void) | |||
441 | { | 378 | { |
442 | int ret; | 379 | int ret; |
443 | 380 | ||
381 | mutex_init(&sd_mtx); | ||
444 | semaphore_init(&transfer_completion_signal, 1, 0); | 382 | semaphore_init(&transfer_completion_signal, 1, 0); |
445 | semaphore_init(&command_completion_signal, 1, 0); | 383 | semaphore_init(&command_completion_signal, 1, 0); |
446 | 384 | ||
@@ -450,13 +388,6 @@ int sd_init(void) | |||
450 | if(ret < 0) | 388 | if(ret < 0) |
451 | return ret; | 389 | return ret; |
452 | 390 | ||
453 | /* init mutex */ | ||
454 | mutex_init(&sd_mtx); | ||
455 | |||
456 | queue_init(&sd_queue, true); | ||
457 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | ||
458 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | ||
459 | |||
460 | return 0; | 391 | return 0; |
461 | } | 392 | } |
462 | 393 | ||
@@ -523,7 +454,7 @@ int sd_read_sectors(IF_MD(int drive,) unsigned long start, int count, | |||
523 | unsigned char *dst; | 454 | unsigned char *dst; |
524 | 455 | ||
525 | mutex_lock(&sd_mtx); | 456 | mutex_lock(&sd_mtx); |
526 | sd_enable(true); | 457 | enable_controller(true); |
527 | 458 | ||
528 | if (count <= 0 || start + count > card_info.numblocks) | 459 | if (count <= 0 || start + count > card_info.numblocks) |
529 | return -1; | 460 | return -1; |
@@ -627,7 +558,7 @@ int sd_read_sectors(IF_MD(int drive,) unsigned long start, int count, | |||
627 | 558 | ||
628 | } /* while (retry_cnt++ < 20) */ | 559 | } /* while (retry_cnt++ < 20) */ |
629 | 560 | ||
630 | sd_enable(false); | 561 | enable_controller(false); |
631 | mutex_unlock(&sd_mtx); | 562 | mutex_unlock(&sd_mtx); |
632 | 563 | ||
633 | return ret; | 564 | return ret; |
@@ -659,7 +590,7 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count, | |||
659 | /* bool card_selected = false; */ | 590 | /* bool card_selected = false; */ |
660 | 591 | ||
661 | mutex_lock(&sd_mtx); | 592 | mutex_lock(&sd_mtx); |
662 | sd_enable(true); | 593 | enable_controller(true); |
663 | 594 | ||
664 | if (count <= 0 || start + count > card_info.numblocks) | 595 | if (count <= 0 || start + count > card_info.numblocks) |
665 | return -1; | 596 | return -1; |
@@ -731,7 +662,7 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count, | |||
731 | break; | 662 | break; |
732 | } | 663 | } |
733 | 664 | ||
734 | sd_enable(false); | 665 | enable_controller(false); |
735 | mutex_unlock(&sd_mtx); | 666 | mutex_unlock(&sd_mtx); |
736 | 667 | ||
737 | #ifdef RK27XX_SD_DEBUG | 668 | #ifdef RK27XX_SD_DEBUG |
@@ -746,17 +677,9 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count, | |||
746 | 677 | ||
747 | void sd_enable(bool on) | 678 | void sd_enable(bool on) |
748 | { | 679 | { |
749 | /* enable or disable clock signal for SD module */ | 680 | mutex_lock(&sd_mtx); |
750 | if (on) | 681 | enable_controller(on); |
751 | { | 682 | mutex_unlock(&sd_mtx); |
752 | SCU_CLKCFG &= ~CLKCFG_SD; | ||
753 | led(true); | ||
754 | } | ||
755 | else | ||
756 | { | ||
757 | SCU_CLKCFG |= CLKCFG_SD; | ||
758 | led(false); | ||
759 | } | ||
760 | } | 683 | } |
761 | 684 | ||
762 | #ifndef BOOTLOADER | 685 | #ifndef BOOTLOADER |
@@ -788,18 +711,13 @@ bool sd_present(IF_MD_NONVOID(int drive)) | |||
788 | 711 | ||
789 | static int sd_oneshot_callback(struct timeout *tmo) | 712 | static int sd_oneshot_callback(struct timeout *tmo) |
790 | { | 713 | { |
791 | (void)tmo; | ||
792 | |||
793 | /* This is called only if the state was stable for 300ms - check state | 714 | /* This is called only if the state was stable for 300ms - check state |
794 | * and post appropriate event. */ | 715 | * and post appropriate event. */ |
795 | if (card_detect_target()) | 716 | queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED : |
796 | { | 717 | SYS_HOTSWAP_EXTRACTED, |
797 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 718 | sd_first_drive); |
798 | } | ||
799 | else | ||
800 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
801 | |||
802 | return 0; | 719 | return 0; |
720 | (void)tmo; | ||
803 | } | 721 | } |
804 | 722 | ||
805 | /* interrupt handler for SD detect */ | 723 | /* interrupt handler for SD detect */ |
@@ -809,9 +727,42 @@ static int sd_oneshot_callback(struct timeout *tmo) | |||
809 | #ifdef CONFIG_STORAGE_MULTI | 727 | #ifdef CONFIG_STORAGE_MULTI |
810 | int sd_num_drives(int first_drive) | 728 | int sd_num_drives(int first_drive) |
811 | { | 729 | { |
812 | (void)first_drive; | ||
813 | |||
814 | /* we have only one SD drive */ | 730 | /* we have only one SD drive */ |
731 | sd_first_drive = first_drive; | ||
815 | return 1; | 732 | return 1; |
816 | } | 733 | } |
817 | #endif /* CONFIG_STORAGE_MULTI */ | 734 | #endif /* CONFIG_STORAGE_MULTI */ |
735 | |||
736 | int sd_event(long id, intptr_t data) | ||
737 | { | ||
738 | int rc = 0; | ||
739 | |||
740 | switch (id) | ||
741 | { | ||
742 | #ifdef HAVE_HOTSWAP | ||
743 | case SYS_HOTSWAP_INSERTED: | ||
744 | case SYS_HOTSWAP_EXTRACTED: | ||
745 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
746 | |||
747 | /* Force card init for new card, re-init for re-inserted one or | ||
748 | * clear if the last attempt to init failed with an error. */ | ||
749 | card_info.initialized = 0; | ||
750 | |||
751 | if (id == SYS_HOTSWAP_INSERTED) | ||
752 | { | ||
753 | enable_controller(true); | ||
754 | rc = sd_init_card(); | ||
755 | enable_controller(false); | ||
756 | } | ||
757 | |||
758 | mutex_unlock(&sd_mtx); | ||
759 | break; | ||
760 | #endif /* HAVE_HOTSWAP */ | ||
761 | default: | ||
762 | rc = storage_event_default_handler(id, data, last_disk_activity, | ||
763 | STORAGE_SD); | ||
764 | break; | ||
765 | } | ||
766 | |||
767 | return rc; | ||
768 | } | ||