summaryrefslogtreecommitdiff
path: root/firmware/target/arm/sandisk/ata-c200_e200.c
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2008-03-09 14:49:10 +0000
committerJens Arnold <amiconn@rockbox.org>2008-03-09 14:49:10 +0000
commited8402ca5ec33f70ac6b28531b05a22c0cf75f9c (patch)
tree2e7b62e5d6387fb9655946f1e87bdaddb277a36f /firmware/target/arm/sandisk/ata-c200_e200.c
parentbc092ad6b998c69ec329a3fca0ed7c076a763aa0 (diff)
downloadrockbox-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/sandisk/ata-c200_e200.c')
-rw-r--r--firmware/target/arm/sandisk/ata-c200_e200.c140
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
1273static bool sd1_oneshot_callback(struct timeout *tmo) 1249static 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 */