aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/wbsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/wbsd.c')
-rw-r--r--drivers/mmc/wbsd.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index b7fbd30b49a..0bd9b53fa89 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1051,6 +1051,20 @@ static struct mmc_host_ops wbsd_ops = {
1051\*****************************************************************************/ 1051\*****************************************************************************/
1052 1052
1053/* 1053/*
1054 * Helper function for card detection
1055 */
1056static void wbsd_detect_card(unsigned long data)
1057{
1058 struct wbsd_host *host = (struct wbsd_host*)data;
1059
1060 BUG_ON(host == NULL);
1061
1062 DBG("Executing card detection\n");
1063
1064 mmc_detect_change(host->mmc);
1065}
1066
1067/*
1054 * Tasklets 1068 * Tasklets
1055 */ 1069 */
1056 1070
@@ -1075,7 +1089,6 @@ static void wbsd_tasklet_card(unsigned long param)
1075{ 1089{
1076 struct wbsd_host* host = (struct wbsd_host*)param; 1090 struct wbsd_host* host = (struct wbsd_host*)param;
1077 u8 csr; 1091 u8 csr;
1078 int change = 0;
1079 1092
1080 spin_lock(&host->lock); 1093 spin_lock(&host->lock);
1081 1094
@@ -1094,14 +1107,20 @@ static void wbsd_tasklet_card(unsigned long param)
1094 { 1107 {
1095 DBG("Card inserted\n"); 1108 DBG("Card inserted\n");
1096 host->flags |= WBSD_FCARD_PRESENT; 1109 host->flags |= WBSD_FCARD_PRESENT;
1097 change = 1; 1110
1111 /*
1112 * Delay card detection to allow electrical connections
1113 * to stabilise.
1114 */
1115 mod_timer(&host->timer, jiffies + HZ/2);
1098 } 1116 }
1117
1118 spin_unlock(&host->lock);
1099 } 1119 }
1100 else if (host->flags & WBSD_FCARD_PRESENT) 1120 else if (host->flags & WBSD_FCARD_PRESENT)
1101 { 1121 {
1102 DBG("Card removed\n"); 1122 DBG("Card removed\n");
1103 host->flags &= ~WBSD_FCARD_PRESENT; 1123 host->flags &= ~WBSD_FCARD_PRESENT;
1104 change = 1;
1105 1124
1106 if (host->mrq) 1125 if (host->mrq)
1107 { 1126 {
@@ -1112,15 +1131,14 @@ static void wbsd_tasklet_card(unsigned long param)
1112 host->mrq->cmd->error = MMC_ERR_FAILED; 1131 host->mrq->cmd->error = MMC_ERR_FAILED;
1113 tasklet_schedule(&host->finish_tasklet); 1132 tasklet_schedule(&host->finish_tasklet);
1114 } 1133 }
1115 } 1134
1116 1135 /*
1117 /* 1136 * Unlock first since we might get a call back.
1118 * Unlock first since we might get a call back. 1137 */
1119 */ 1138 spin_unlock(&host->lock);
1120 spin_unlock(&host->lock);
1121 1139
1122 if (change)
1123 mmc_detect_change(host->mmc); 1140 mmc_detect_change(host->mmc);
1141 }
1124} 1142}
1125 1143
1126static void wbsd_tasklet_fifo(unsigned long param) 1144static void wbsd_tasklet_fifo(unsigned long param)
@@ -1325,6 +1343,13 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
1325 spin_lock_init(&host->lock); 1343 spin_lock_init(&host->lock);
1326 1344
1327 /* 1345 /*
1346 * Set up detection timer
1347 */
1348 init_timer(&host->timer);
1349 host->timer.data = (unsigned long)host;
1350 host->timer.function = wbsd_detect_card;
1351
1352 /*
1328 * Maximum number of segments. Worst case is one sector per segment 1353 * Maximum number of segments. Worst case is one sector per segment
1329 * so this will be 64kB/512. 1354 * so this will be 64kB/512.
1330 */ 1355 */
@@ -1351,11 +1376,17 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
1351static void __devexit wbsd_free_mmc(struct device* dev) 1376static void __devexit wbsd_free_mmc(struct device* dev)
1352{ 1377{
1353 struct mmc_host* mmc; 1378 struct mmc_host* mmc;
1379 struct wbsd_host* host;
1354 1380
1355 mmc = dev_get_drvdata(dev); 1381 mmc = dev_get_drvdata(dev);
1356 if (!mmc) 1382 if (!mmc)
1357 return; 1383 return;
1358 1384
1385 host = mmc_priv(mmc);
1386 BUG_ON(host == NULL);
1387
1388 del_timer_sync(&host->timer);
1389
1359 mmc_free_host(mmc); 1390 mmc_free_host(mmc);
1360 1391
1361 dev_set_drvdata(dev, NULL); 1392 dev_set_drvdata(dev, NULL);