diff options
| author | Pierre Ossman <drzeus@drzeus.cx> | 2005-07-01 07:13:55 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2005-07-01 07:13:55 -0400 |
| commit | 6e6293dd3d4372c114674266158053d049366a0d (patch) | |
| tree | ffc7a4a22e2d8faff62ef32988d378af48dbc1ec /drivers/mmc/wbsd.c | |
| parent | 7b09cdac5af1e13ab4b30421ae5c4b7953c26841 (diff) | |
[PATCH] MMC: wbsd delayed insertion
Wait 0.5 seconds before scanning for cards after an insertion interrupt.
The electrical connection needs this time to stabilise for some cards.
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/mmc/wbsd.c')
| -rw-r--r-- | drivers/mmc/wbsd.c | 51 |
1 files changed, 41 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); |
