diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/wbsd.c | 51 | ||||
-rw-r--r-- | drivers/mmc/wbsd.h | 2 |
2 files changed, 43 insertions, 10 deletions
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index b7fbd30b49a0..0bd9b53fa898 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 | */ | ||
1056 | static 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 | ||
1126 | static void wbsd_tasklet_fifo(unsigned long param) | 1144 | static 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) | |||
1351 | static void __devexit wbsd_free_mmc(struct device* dev) | 1376 | static 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); |
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h index 864f30828d01..9f5383e6e593 100644 --- a/drivers/mmc/wbsd.h +++ b/drivers/mmc/wbsd.h | |||
@@ -187,4 +187,6 @@ struct wbsd_host | |||
187 | struct tasklet_struct timeout_tasklet; | 187 | struct tasklet_struct timeout_tasklet; |
188 | struct tasklet_struct finish_tasklet; | 188 | struct tasklet_struct finish_tasklet; |
189 | struct tasklet_struct block_tasklet; | 189 | struct tasklet_struct block_tasklet; |
190 | |||
191 | struct timer_list timer; /* Card detection timer */ | ||
190 | }; | 192 | }; |