diff options
author | Jens Arnold <amiconn@rockbox.org> | 2008-03-09 14:49:10 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2008-03-09 14:49:10 +0000 |
commit | ed8402ca5ec33f70ac6b28531b05a22c0cf75f9c (patch) | |
tree | 2e7b62e5d6387fb9655946f1e87bdaddb277a36f /firmware/target/arm | |
parent | bc092ad6b998c69ec329a3fca0ed7c076a763aa0 (diff) | |
download | rockbox-ed8402ca5ec33f70ac6b28531b05a22c0cf75f9c.tar.gz rockbox-ed8402ca5ec33f70ac6b28531b05a22c0cf75f9c.zip |
Sansa SD card driver: Simplify hotswap handling, and make it send the insert/remove events while filesystem access is blocked. Also use atomic GPIO bit manipulation where possible, and protect the interrupt level manipulation in the ISR from interrupts arriving at the same time.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16592 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/sandisk/ata-c200_e200.c | 140 |
1 files changed, 59 insertions, 81 deletions
diff --git a/firmware/target/arm/sandisk/ata-c200_e200.c b/firmware/target/arm/sandisk/ata-c200_e200.c index ea6c2c5eaf..7a4328df80 100644 --- a/firmware/target/arm/sandisk/ata-c200_e200.c +++ b/firmware/target/arm/sandisk/ata-c200_e200.c | |||
@@ -531,11 +531,11 @@ static void sd_card_mux(int card_no) | |||
531 | { | 531 | { |
532 | GPO32_VAL |= 0x4; | 532 | GPO32_VAL |= 0x4; |
533 | 533 | ||
534 | GPIOA_ENABLE &= ~0x7a; | 534 | GPIO_CLEAR_BITWISE(GPIOA_ENABLE, 0x7a); |
535 | GPIOA_OUTPUT_EN &= ~0x7a; | 535 | GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x7a); |
536 | GPIOD_ENABLE |= 0x1f; | 536 | GPIO_SET_BITWISE(GPIOD_ENABLE, 0x1f); |
537 | GPIOD_OUTPUT_VAL |= 0x1f; | 537 | GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL, 0x1f); |
538 | GPIOD_OUTPUT_EN |= 0x1f; | 538 | GPIO_SET_BITWISE(GPIOD_OUTPUT_EN, 0x1f); |
539 | 539 | ||
540 | outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014); | 540 | outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014); |
541 | } | 541 | } |
@@ -543,11 +543,11 @@ static void sd_card_mux(int card_no) | |||
543 | { | 543 | { |
544 | GPO32_VAL &= ~0x4; | 544 | GPO32_VAL &= ~0x4; |
545 | 545 | ||
546 | GPIOD_ENABLE &= ~0x1f; | 546 | GPIO_CLEAR_BITWISE(GPIOD_ENABLE, 0x1f); |
547 | GPIOD_OUTPUT_EN &= ~0x1f; | 547 | GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_EN, 0x1f); |
548 | GPIOA_ENABLE |= 0x7a; | 548 | GPIO_SET_BITWISE(GPIOA_ENABLE, 0x7a); |
549 | GPIOA_OUTPUT_VAL |= 0x7a; | 549 | GPIO_SET_BITWISE(GPIOA_OUTPUT_VAL, 0x7a); |
550 | GPIOA_OUTPUT_EN |= 0x7a; | 550 | GPIO_SET_BITWISE( GPIOA_OUTPUT_EN, 0x7a); |
551 | 551 | ||
552 | outl(inl(0x70000014) & ~(0x3ffff), 0x70000014); | 552 | outl(inl(0x70000014) & ~(0x3ffff), 0x70000014); |
553 | } | 553 | } |
@@ -556,11 +556,11 @@ static void sd_card_mux(int card_no) | |||
556 | { | 556 | { |
557 | GPO32_VAL |= 0x4; | 557 | GPO32_VAL |= 0x4; |
558 | 558 | ||
559 | GPIOD_ENABLE &= ~0x1f; | 559 | GPIO_CLEAR_BITWISE(GPIOD_ENABLE, 0x1f); |
560 | GPIOD_OUTPUT_EN &= ~0x1f; | 560 | GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_EN, 0x1f); |
561 | GPIOA_ENABLE |= 0x7a; | 561 | GPIO_SET_BITWISE(GPIOA_ENABLE, 0x7a); |
562 | GPIOA_OUTPUT_VAL |= 0x7a; | 562 | GPIO_SET_BITWISE(GPIOA_OUTPUT_VAL, 0x7a); |
563 | GPIOA_OUTPUT_EN |= 0x7a; | 563 | GPIO_SET_BITWISE( GPIOA_OUTPUT_EN, 0x7a); |
564 | 564 | ||
565 | outl(inl(0x70000014) & ~(0x3ffff), 0x70000014); | 565 | outl(inl(0x70000014) & ~(0x3ffff), 0x70000014); |
566 | } | 566 | } |
@@ -568,11 +568,11 @@ static void sd_card_mux(int card_no) | |||
568 | { | 568 | { |
569 | GPO32_VAL &= ~0x4; | 569 | GPO32_VAL &= ~0x4; |
570 | 570 | ||
571 | GPIOA_ENABLE &= ~0x7a; | 571 | GPIO_CLEAR_BITWISE(GPIOA_ENABLE, 0x7a); |
572 | GPIOA_OUTPUT_EN &= ~0x7a; | 572 | GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x7a); |
573 | GPIOD_ENABLE |= 0x1f; | 573 | GPIO_SET_BITWISE(GPIOD_ENABLE, 0x1f); |
574 | GPIOD_OUTPUT_VAL |= 0x1f; | 574 | GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL, 0x1f); |
575 | GPIOD_OUTPUT_EN |= 0x1f; | 575 | GPIO_SET_BITWISE(GPIOD_OUTPUT_EN, 0x1f); |
576 | 576 | ||
577 | outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014); | 577 | outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014); |
578 | } | 578 | } |
@@ -1044,39 +1044,16 @@ static void sd_thread(void) | |||
1044 | switch ( ev.id ) | 1044 | switch ( ev.id ) |
1045 | { | 1045 | { |
1046 | #ifdef HAVE_HOTSWAP | 1046 | #ifdef HAVE_HOTSWAP |
1047 | case SD_HOTSWAP: | 1047 | case SYS_HOTSWAP_INSERTED: |
1048 | { | 1048 | disk_mount(1); /* mount microSD card */ |
1049 | int action = SDA_NONE; | 1049 | queue_broadcast(SYS_FS_CHANGED, 0); |
1050 | |||
1051 | /* Lock to keep us from messing with this variable while an init | ||
1052 | may be in progress */ | ||
1053 | mutex_lock(&sd_mtx); | ||
1054 | card_info[1].initialized = 0; | ||
1055 | sd_status[1].retry = 0; | ||
1056 | |||
1057 | /* Either unmount because the card was pulled or unmount and | ||
1058 | remount if already mounted since multiple messages may be | ||
1059 | generated for the same event - like someone inserting a new | ||
1060 | card before anything detects the old one pulled :) */ | ||
1061 | if (disk_unmount(1) != 0) /* release "by force" */ | ||
1062 | action |= SDA_UNMOUNTED; | ||
1063 | |||
1064 | if (ev.data != 0 && disk_mount(1) != 0) /* mount SD-CARD */ | ||
1065 | action |= SDA_MOUNTED; | ||
1066 | |||
1067 | if (action & SDA_UNMOUNTED) | ||
1068 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
1069 | |||
1070 | if (action & SDA_MOUNTED) | ||
1071 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | ||
1072 | |||
1073 | if (action != SDA_NONE) | ||
1074 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
1075 | |||
1076 | mutex_unlock(&sd_mtx); | ||
1077 | break; | 1050 | break; |
1078 | } /* SD_HOTSWAP */ | 1051 | |
1079 | #endif /* HAVE_HOTSWAP */ | 1052 | case SYS_HOTSWAP_EXTRACTED: |
1053 | disk_unmount(1); /* release "by force" */ | ||
1054 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
1055 | break; | ||
1056 | #endif | ||
1080 | case SYS_TIMEOUT: | 1057 | case SYS_TIMEOUT: |
1081 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | 1058 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) |
1082 | { | 1059 | { |
@@ -1097,9 +1074,8 @@ static void sd_thread(void) | |||
1097 | case SYS_USB_CONNECTED: | 1074 | case SYS_USB_CONNECTED: |
1098 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | 1075 | usb_acknowledge(SYS_USB_CONNECTED_ACK); |
1099 | /* Wait until the USB cable is extracted again */ | 1076 | /* Wait until the USB cable is extracted again */ |
1100 | #ifndef HAVE_USBSTACK | ||
1101 | usb_wait_for_disconnect(&sd_queue); | 1077 | usb_wait_for_disconnect(&sd_queue); |
1102 | #endif | 1078 | |
1103 | break; | 1079 | break; |
1104 | case SYS_USB_DISCONNECTED: | 1080 | case SYS_USB_DISCONNECTED: |
1105 | usb_acknowledge(SYS_USB_DISCONNECTED_ACK); | 1081 | usb_acknowledge(SYS_USB_DISCONNECTED_ACK); |
@@ -1170,22 +1146,22 @@ int ata_init(void) | |||
1170 | outl(inl(0x7000008c) & ~(0x4), 0x7000008c); | 1146 | outl(inl(0x7000008c) & ~(0x4), 0x7000008c); |
1171 | GPO32_ENABLE |= 0x4; | 1147 | GPO32_ENABLE |= 0x4; |
1172 | 1148 | ||
1173 | GPIOG_ENABLE |= (0x3 << 5); | 1149 | GPIO_SET_BITWISE(GPIOG_ENABLE, (0x3 << 5)); |
1174 | GPIOG_OUTPUT_EN |= (0x3 << 5); | 1150 | GPIO_SET_BITWISE(GPIOG_OUTPUT_EN, (0x3 << 5)); |
1175 | GPIOG_OUTPUT_VAL |= (0x3 << 5); | 1151 | GPIO_SET_BITWISE(GPIOG_OUTPUT_VAL, (0x3 << 5)); |
1176 | 1152 | ||
1177 | #ifdef HAVE_HOTSWAP | 1153 | #ifdef HAVE_HOTSWAP |
1178 | /* enable card detection port - mask interrupt first */ | 1154 | /* enable card detection port - mask interrupt first */ |
1179 | #ifdef SANSA_E200 | 1155 | #ifdef SANSA_E200 |
1180 | GPIOA_INT_EN &= ~0x80; | 1156 | GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80); |
1181 | 1157 | ||
1182 | GPIOA_OUTPUT_EN &= ~0x80; | 1158 | GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x80); |
1183 | GPIOA_ENABLE |= 0x80; | 1159 | GPIO_SET_BITWISE(GPIOA_ENABLE, 0x80); |
1184 | #elif defined SANSA_C200 | 1160 | #elif defined SANSA_C200 |
1185 | GPIOL_INT_EN &= ~0x08; | 1161 | GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08); |
1186 | 1162 | ||
1187 | GPIOL_OUTPUT_EN &= ~0x08; | 1163 | GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_EN, 0x08); |
1188 | GPIOL_ENABLE |= 0x08; | 1164 | GPIO_SET_BITWISE(GPIOL_ENABLE, 0x08); |
1189 | #endif | 1165 | #endif |
1190 | #endif | 1166 | #endif |
1191 | sd_select_device(0); | 1167 | sd_select_device(0); |
@@ -1205,18 +1181,18 @@ int ata_init(void) | |||
1205 | CPU_INT_EN = HI_MASK; | 1181 | CPU_INT_EN = HI_MASK; |
1206 | CPU_HI_INT_EN = GPIO0_MASK; | 1182 | CPU_HI_INT_EN = GPIO0_MASK; |
1207 | 1183 | ||
1208 | GPIOA_INT_LEV = (GPIOA_INT_LEV & ~0x80) | (~GPIOA_INPUT_VAL & 0x80); | 1184 | GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80); |
1209 | 1185 | ||
1210 | GPIOA_INT_CLR = 0x80; | 1186 | GPIOA_INT_CLR = 0x80; |
1211 | GPIOA_INT_EN |= 0x80; | 1187 | GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80); |
1212 | #elif defined SANSA_C200 | 1188 | #elif defined SANSA_C200 |
1213 | CPU_INT_EN = HI_MASK; | 1189 | CPU_INT_EN = HI_MASK; |
1214 | CPU_HI_INT_EN = GPIO2_MASK; | 1190 | CPU_HI_INT_EN = GPIO2_MASK; |
1215 | 1191 | ||
1216 | GPIOL_INT_LEV = (GPIOL_INT_LEV & ~0x08) | (~GPIOL_INPUT_VAL & 0x08); | 1192 | GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08); |
1217 | 1193 | ||
1218 | GPIOL_INT_CLR = 0x08; | 1194 | GPIOL_INT_CLR = 0x08; |
1219 | GPIOL_INT_EN |= 0x08; | 1195 | GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); |
1220 | #endif | 1196 | #endif |
1221 | #endif | 1197 | #endif |
1222 | } | 1198 | } |
@@ -1272,9 +1248,15 @@ bool card_detect_target(void) | |||
1272 | 1248 | ||
1273 | static bool sd1_oneshot_callback(struct timeout *tmo) | 1249 | static bool sd1_oneshot_callback(struct timeout *tmo) |
1274 | { | 1250 | { |
1275 | /* Take final state only - insert/remove is bouncy */ | 1251 | (void)tmo; |
1276 | queue_remove_from_head(&sd_queue, SD_HOTSWAP); | 1252 | |
1277 | queue_post(&sd_queue, SD_HOTSWAP, tmo->data); | 1253 | /* This is called only if the state was stable for 300ms - check state |
1254 | * and post appropriate event. */ | ||
1255 | if (card_detect_target()) | ||
1256 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | ||
1257 | else | ||
1258 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
1259 | |||
1278 | return false; | 1260 | return false; |
1279 | } | 1261 | } |
1280 | 1262 | ||
@@ -1284,22 +1266,18 @@ void microsd_int(void) | |||
1284 | static struct timeout sd1_oneshot; | 1266 | static struct timeout sd1_oneshot; |
1285 | 1267 | ||
1286 | #ifdef SANSA_E200 | 1268 | #ifdef SANSA_E200 |
1287 | int detect = GPIOA_INPUT_VAL & 0x80; | 1269 | GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80); |
1288 | 1270 | GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80); | |
1289 | GPIOA_INT_LEV = (GPIOA_INT_LEV & ~0x80) | (detect ^ 0x80); | ||
1290 | GPIOA_INT_CLR = 0x80; | 1271 | GPIOA_INT_CLR = 0x80; |
1272 | GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80); | ||
1291 | 1273 | ||
1292 | timeout_register(&sd1_oneshot, sd1_oneshot_callback, | ||
1293 | detect ? 1 : HZ/2, detect == 0); | ||
1294 | #elif defined SANSA_C200 | 1274 | #elif defined SANSA_C200 |
1295 | int detect = GPIOL_INPUT_VAL & 0x08; | 1275 | GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08); |
1296 | 1276 | GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08); | |
1297 | GPIOL_INT_LEV = (GPIOL_INT_LEV & ~0x08) | (detect ^ 0x08); | ||
1298 | GPIOL_INT_CLR = 0x08; | 1277 | GPIOL_INT_CLR = 0x08; |
1299 | 1278 | GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); | |
1300 | timeout_register(&sd1_oneshot, sd1_oneshot_callback, | ||
1301 | detect ? HZ/2 : 1, detect != 0); | ||
1302 | #endif | 1279 | #endif |
1280 | timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0); | ||
1303 | 1281 | ||
1304 | } | 1282 | } |
1305 | #endif /* HAVE_HOTSWAP */ | 1283 | #endif /* HAVE_HOTSWAP */ |