diff options
author | Thomas Martitz <kugel@rockbox.org> | 2014-02-07 18:30:50 +0100 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2014-02-23 20:23:52 +0100 |
commit | f6c26d33a4e15d966597bc9d66c1f33328a750af (patch) | |
tree | 5e0e4d0189c856010a78ce0b79cdc3c3cb5c1354 /firmware/target/hosted/samsungypr/ypr0/system-ypr0.c | |
parent | 46137ebd4d59d7a91d0b8d98d846a3fd2ec70f5c (diff) | |
download | rockbox-f6c26d33a4e15d966597bc9d66c1f33328a750af.tar.gz rockbox-f6c26d33a4e15d966597bc9d66c1f33328a750af.zip |
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
Diffstat (limited to 'firmware/target/hosted/samsungypr/ypr0/system-ypr0.c')
-rw-r--r-- | firmware/target/hosted/samsungypr/ypr0/system-ypr0.c | 165 |
1 files changed, 160 insertions, 5 deletions
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 @@ | |||
19 | ****************************************************************************/ | 19 | ****************************************************************************/ |
20 | 20 | ||
21 | #include <stdlib.h> | 21 | #include <stdlib.h> |
22 | #include <string.h> | ||
23 | #include <inttypes.h> | 22 | #include <inttypes.h> |
24 | #include <unistd.h> | 23 | #include <unistd.h> |
24 | #include <sys/mount.h> | ||
25 | #include <errno.h> | ||
26 | |||
25 | #include "system.h" | 27 | #include "system.h" |
28 | #include "kernel.h" | ||
29 | #include "thread.h" | ||
30 | |||
31 | #include "string-extra.h" | ||
26 | #include "panic.h" | 32 | #include "panic.h" |
27 | #include "debug.h" | 33 | #include "debug.h" |
28 | #include "hostfs.h" | 34 | #include "storage.h" |
29 | 35 | #include "mv.h" | |
30 | #include "ascodec.h" | 36 | #include "ascodec.h" |
31 | #include "gpio-ypr.h" | 37 | #include "gpio-ypr.h" |
38 | #include "ascodec.h" | ||
39 | #include "backlight.h" | ||
40 | #include "rbunicode.h" | ||
41 | #include "logdiskf.h" | ||
32 | 42 | ||
33 | void power_off(void) | 43 | void power_off(void) |
34 | { | 44 | { |
@@ -61,15 +71,160 @@ void system_exception_wait(void) | |||
61 | system_reboot(); | 71 | system_reboot(); |
62 | } | 72 | } |
63 | 73 | ||
74 | /* MicroSD card removal / insertion management */ | ||
75 | |||
76 | bool hostfs_removable(IF_MD_NONVOID(int drive)) | ||
77 | { | ||
78 | #ifdef HAVE_MULTIDRIVE | ||
79 | if (drive > 0) /* Active LOW */ | ||
80 | return true; | ||
81 | else | ||
82 | #endif | ||
83 | return false; /* internal: always present */ | ||
84 | } | ||
85 | |||
86 | bool hostfs_present(IF_MD_NONVOID(int drive)) | ||
87 | { | ||
88 | #ifdef HAVE_MULTIDRIVE | ||
89 | if (drive > 0) /* Active LOW */ | ||
90 | return (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_SD_SENSE, 0, 0)); | ||
91 | else | ||
92 | #endif | ||
93 | return true; /* internal: always present */ | ||
94 | } | ||
95 | |||
96 | #ifdef HAVE_HOTSWAP | ||
97 | bool volume_removable(int volume) | ||
98 | { | ||
99 | /* don't support more than one partition yet, so volume == drive */ | ||
100 | return hostfs_removable(volume); | ||
101 | } | ||
102 | |||
103 | bool volume_present(int volume) | ||
104 | { | ||
105 | /* don't support more than one partition yet, so volume == drive */ | ||
106 | return hostfs_present(volume); | ||
107 | } | ||
108 | #endif | ||
109 | |||
110 | static int unmount_sd(void) | ||
111 | { | ||
112 | int ret; | ||
113 | do | ||
114 | { | ||
115 | ret = umount("/mnt/mmc"); | ||
116 | } while (ret && errno != EBUSY && errno != EINVAL); | ||
117 | |||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static int mount_sd(void) | ||
122 | { | ||
123 | int ret; | ||
124 | /* kludge to make sure we get our wanted mount flags. This is needed | ||
125 | * when the sd was already mounted before we booted */ | ||
126 | unmount_sd(); | ||
127 | char iocharset[64] = "iocharset="; | ||
128 | strlcat(iocharset, get_current_codepage_name_linux(), sizeof(iocharset)); | ||
129 | ret = mount("/dev/mmcblk0p1", "/mnt/mmc", "vfat", | ||
130 | MS_MGC_VAL | MS_SYNCHRONOUS | MS_RELATIME, | ||
131 | iocharset); | ||
132 | /* failure probably means the kernel does not support the iocharset. | ||
133 | * retry without to load the default */ | ||
134 | if (ret == -1) | ||
135 | ret = mount("/dev/mmcblk0p1", "/mnt/mmc", "vfat", | ||
136 | MS_MGC_VAL | MS_SYNCHRONOUS | MS_RELATIME, NULL); | ||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | #ifdef HAVE_HOTSWAP | ||
141 | |||
142 | static int sd_thread_stack[DEFAULT_STACK_SIZE]; | ||
143 | |||
144 | enum { | ||
145 | STATE_POLL, | ||
146 | STATE_DEBOUNCE, | ||
147 | STATE_MOUNT, | ||
148 | }; | ||
149 | |||
150 | static void NORETURN_ATTR sd_thread(void) | ||
151 | { | ||
152 | int ret, state = STATE_POLL; | ||
153 | bool last_present, present; | ||
154 | int attempts = 0; | ||
155 | |||
156 | last_present = present = storage_present(1); /* shut up gcc */ | ||
157 | |||
158 | while (1) | ||
159 | { | ||
160 | switch (state) | ||
161 | { | ||
162 | case STATE_POLL: | ||
163 | sleep(HZ/3); | ||
164 | attempts = 0; | ||
165 | present = storage_present(1); | ||
166 | if (last_present != present) | ||
167 | state = STATE_DEBOUNCE; | ||
168 | break; | ||
169 | |||
170 | case STATE_DEBOUNCE: | ||
171 | sleep(HZ/5); | ||
172 | present = storage_present(1); | ||
173 | if (last_present == present) | ||
174 | { | ||
175 | if (present) | ||
176 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | ||
177 | else | ||
178 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
179 | state = STATE_MOUNT; | ||
180 | } | ||
181 | else | ||
182 | state = STATE_POLL; | ||
183 | break; | ||
184 | |||
185 | case STATE_MOUNT: | ||
186 | sleep(HZ/10); | ||
187 | if (present) | ||
188 | ret = mount_sd(); | ||
189 | else | ||
190 | ret = unmount_sd(); | ||
191 | if (ret == 0) | ||
192 | { | ||
193 | NOTEF("Successfully %smounted SD card\n", present ? "":"un"); | ||
194 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
195 | state = STATE_POLL; | ||
196 | } | ||
197 | else if (++attempts > 20) /* stop retrying after 2s */ | ||
198 | { | ||
199 | ERRORF("Failed to %smount SD card. Giving up.", present ? "":"un"); | ||
200 | state = STATE_POLL; | ||
201 | } | ||
202 | /* else: need to retry a few times because the kernel is | ||
203 | * busy setting up the SD (=> do not change state) */ | ||
204 | break; | ||
205 | } | ||
206 | last_present = present; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | #endif | ||
211 | |||
64 | void hostfs_init(void) | 212 | void hostfs_init(void) |
65 | { | 213 | { |
66 | /* stub */ | 214 | /* Setup GPIO pin for microSD sense, copied from OF */ |
215 | gpio_control(DEV_CTRL_GPIO_SET_MUX, GPIO_SD_SENSE, CONFIG_DEFAULT, 0); | ||
216 | gpio_control(DEV_CTRL_GPIO_SET_INPUT, GPIO_SD_SENSE, CONFIG_DEFAULT, 0); | ||
217 | if (storage_present(IF_MD(1))) | ||
218 | mount_sd(); | ||
219 | #ifdef HAVE_HOTSWAP | ||
220 | create_thread(sd_thread, sd_thread_stack, sizeof(sd_thread_stack), 0, | ||
221 | "sd thread" IF_PRIO(, PRIORITY_BACKGROUND) IF_COP(, CPU)); | ||
222 | #endif | ||
67 | } | 223 | } |
68 | 224 | ||
69 | int hostfs_flush(void) | 225 | int hostfs_flush(void) |
70 | { | 226 | { |
71 | sync(); | 227 | sync(); |
72 | |||
73 | return 0; | 228 | return 0; |
74 | } | 229 | } |
75 | 230 | ||