From f6c26d33a4e15d966597bc9d66c1f33328a750af Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Fri, 7 Feb 2014 18:30:50 +0100 Subject: samsungypr0: Support or mounting the microsd A thread polls the appropriate GPIO pin for sd card presence and mounts using the mount system call. Change-Id: I31ab41c4120f4af64eb6998b7e7b6f9051585efb --- .../target/hosted/samsungypr/ypr0/system-ypr0.c | 165 ++++++++++++++++++++- 1 file changed, 160 insertions(+), 5 deletions(-) (limited to 'firmware/target/hosted/samsungypr/ypr0/system-ypr0.c') diff --git a/firmware/target/hosted/samsungypr/ypr0/system-ypr0.c b/firmware/target/hosted/samsungypr/ypr0/system-ypr0.c index 477b71c6a2..893c710861 100644 --- a/firmware/target/hosted/samsungypr/ypr0/system-ypr0.c +++ b/firmware/target/hosted/samsungypr/ypr0/system-ypr0.c @@ -19,16 +19,26 @@ ****************************************************************************/ #include -#include #include #include +#include +#include + #include "system.h" +#include "kernel.h" +#include "thread.h" + +#include "string-extra.h" #include "panic.h" #include "debug.h" -#include "hostfs.h" - +#include "storage.h" +#include "mv.h" #include "ascodec.h" #include "gpio-ypr.h" +#include "ascodec.h" +#include "backlight.h" +#include "rbunicode.h" +#include "logdiskf.h" void power_off(void) { @@ -61,15 +71,160 @@ void system_exception_wait(void) system_reboot(); } +/* MicroSD card removal / insertion management */ + +bool hostfs_removable(IF_MD_NONVOID(int drive)) +{ +#ifdef HAVE_MULTIDRIVE + if (drive > 0) /* Active LOW */ + return true; + else +#endif + return false; /* internal: always present */ +} + +bool hostfs_present(IF_MD_NONVOID(int drive)) +{ +#ifdef HAVE_MULTIDRIVE + if (drive > 0) /* Active LOW */ + return (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_SD_SENSE, 0, 0)); + else +#endif + return true; /* internal: always present */ +} + +#ifdef HAVE_HOTSWAP +bool volume_removable(int volume) +{ + /* don't support more than one partition yet, so volume == drive */ + return hostfs_removable(volume); +} + +bool volume_present(int volume) +{ + /* don't support more than one partition yet, so volume == drive */ + return hostfs_present(volume); +} +#endif + +static int unmount_sd(void) +{ + int ret; + do + { + ret = umount("/mnt/mmc"); + } while (ret && errno != EBUSY && errno != EINVAL); + + return ret; +} + +static int mount_sd(void) +{ + int ret; + /* kludge to make sure we get our wanted mount flags. This is needed + * when the sd was already mounted before we booted */ + unmount_sd(); + char iocharset[64] = "iocharset="; + strlcat(iocharset, get_current_codepage_name_linux(), sizeof(iocharset)); + ret = mount("/dev/mmcblk0p1", "/mnt/mmc", "vfat", + MS_MGC_VAL | MS_SYNCHRONOUS | MS_RELATIME, + iocharset); + /* failure probably means the kernel does not support the iocharset. + * retry without to load the default */ + if (ret == -1) + ret = mount("/dev/mmcblk0p1", "/mnt/mmc", "vfat", + MS_MGC_VAL | MS_SYNCHRONOUS | MS_RELATIME, NULL); + return ret; +} + +#ifdef HAVE_HOTSWAP + +static int sd_thread_stack[DEFAULT_STACK_SIZE]; + +enum { + STATE_POLL, + STATE_DEBOUNCE, + STATE_MOUNT, +}; + +static void NORETURN_ATTR sd_thread(void) +{ + int ret, state = STATE_POLL; + bool last_present, present; + int attempts = 0; + + last_present = present = storage_present(1); /* shut up gcc */ + + while (1) + { + switch (state) + { + case STATE_POLL: + sleep(HZ/3); + attempts = 0; + present = storage_present(1); + if (last_present != present) + state = STATE_DEBOUNCE; + break; + + case STATE_DEBOUNCE: + sleep(HZ/5); + present = storage_present(1); + if (last_present == present) + { + if (present) + queue_broadcast(SYS_HOTSWAP_INSERTED, 0); + else + queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); + state = STATE_MOUNT; + } + else + state = STATE_POLL; + break; + + case STATE_MOUNT: + sleep(HZ/10); + if (present) + ret = mount_sd(); + else + ret = unmount_sd(); + if (ret == 0) + { + NOTEF("Successfully %smounted SD card\n", present ? "":"un"); + queue_broadcast(SYS_FS_CHANGED, 0); + state = STATE_POLL; + } + else if (++attempts > 20) /* stop retrying after 2s */ + { + ERRORF("Failed to %smount SD card. Giving up.", present ? "":"un"); + state = STATE_POLL; + } + /* else: need to retry a few times because the kernel is + * busy setting up the SD (=> do not change state) */ + break; + } + last_present = present; + } +} + +#endif + void hostfs_init(void) { - /* stub */ + /* Setup GPIO pin for microSD sense, copied from OF */ + gpio_control(DEV_CTRL_GPIO_SET_MUX, GPIO_SD_SENSE, CONFIG_DEFAULT, 0); + gpio_control(DEV_CTRL_GPIO_SET_INPUT, GPIO_SD_SENSE, CONFIG_DEFAULT, 0); + if (storage_present(IF_MD(1))) + mount_sd(); +#ifdef HAVE_HOTSWAP + create_thread(sd_thread, sd_thread_stack, sizeof(sd_thread_stack), 0, + "sd thread" IF_PRIO(, PRIORITY_BACKGROUND) IF_COP(, CPU)); +#endif } int hostfs_flush(void) { sync(); - return 0; } -- cgit v1.2.3