diff options
-rw-r--r-- | drivers/mmc/mmc.c | 12 | ||||
-rw-r--r-- | drivers/mmc/wbsd.c | 64 | ||||
-rw-r--r-- | drivers/mmc/wbsd.h | 3 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 6 |
4 files changed, 70 insertions, 15 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 3c5904834fe8..0a8165974ba7 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c | |||
@@ -457,6 +457,11 @@ static void mmc_idle_cards(struct mmc_host *host) | |||
457 | { | 457 | { |
458 | struct mmc_command cmd; | 458 | struct mmc_command cmd; |
459 | 459 | ||
460 | host->ios.chip_select = MMC_CS_HIGH; | ||
461 | host->ops->set_ios(host, &host->ios); | ||
462 | |||
463 | mmc_delay(1); | ||
464 | |||
460 | cmd.opcode = MMC_GO_IDLE_STATE; | 465 | cmd.opcode = MMC_GO_IDLE_STATE; |
461 | cmd.arg = 0; | 466 | cmd.arg = 0; |
462 | cmd.flags = MMC_RSP_NONE; | 467 | cmd.flags = MMC_RSP_NONE; |
@@ -464,6 +469,11 @@ static void mmc_idle_cards(struct mmc_host *host) | |||
464 | mmc_wait_for_cmd(host, &cmd, 0); | 469 | mmc_wait_for_cmd(host, &cmd, 0); |
465 | 470 | ||
466 | mmc_delay(1); | 471 | mmc_delay(1); |
472 | |||
473 | host->ios.chip_select = MMC_CS_DONTCARE; | ||
474 | host->ops->set_ios(host, &host->ios); | ||
475 | |||
476 | mmc_delay(1); | ||
467 | } | 477 | } |
468 | 478 | ||
469 | /* | 479 | /* |
@@ -475,6 +485,7 @@ static void mmc_power_up(struct mmc_host *host) | |||
475 | 485 | ||
476 | host->ios.vdd = bit; | 486 | host->ios.vdd = bit; |
477 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; | 487 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; |
488 | host->ios.chip_select = MMC_CS_DONTCARE; | ||
478 | host->ios.power_mode = MMC_POWER_UP; | 489 | host->ios.power_mode = MMC_POWER_UP; |
479 | host->ops->set_ios(host, &host->ios); | 490 | host->ops->set_ios(host, &host->ios); |
480 | 491 | ||
@@ -492,6 +503,7 @@ static void mmc_power_off(struct mmc_host *host) | |||
492 | host->ios.clock = 0; | 503 | host->ios.clock = 0; |
493 | host->ios.vdd = 0; | 504 | host->ios.vdd = 0; |
494 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; | 505 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; |
506 | host->ios.chip_select = MMC_CS_DONTCARE; | ||
495 | host->ios.power_mode = MMC_POWER_OFF; | 507 | host->ios.power_mode = MMC_POWER_OFF; |
496 | host->ops->set_ios(host, &host->ios); | 508 | host->ops->set_ios(host, &host->ios); |
497 | } | 509 | } |
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 402c2d661fb2..08ae22aed9e8 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include "wbsd.h" | 42 | #include "wbsd.h" |
43 | 43 | ||
44 | #define DRIVER_NAME "wbsd" | 44 | #define DRIVER_NAME "wbsd" |
45 | #define DRIVER_VERSION "1.3" | 45 | #define DRIVER_VERSION "1.4" |
46 | 46 | ||
47 | #ifdef CONFIG_MMC_DEBUG | 47 | #ifdef CONFIG_MMC_DEBUG |
48 | #define DBG(x...) \ | 48 | #define DBG(x...) \ |
@@ -960,8 +960,9 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) | |||
960 | struct wbsd_host* host = mmc_priv(mmc); | 960 | struct wbsd_host* host = mmc_priv(mmc); |
961 | u8 clk, setup, pwr; | 961 | u8 clk, setup, pwr; |
962 | 962 | ||
963 | DBGF("clock %uHz busmode %u powermode %u Vdd %u\n", | 963 | DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u\n", |
964 | ios->clock, ios->bus_mode, ios->power_mode, ios->vdd); | 964 | ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, |
965 | ios->vdd); | ||
965 | 966 | ||
966 | spin_lock_bh(&host->lock); | 967 | spin_lock_bh(&host->lock); |
967 | 968 | ||
@@ -1003,13 +1004,11 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) | |||
1003 | 1004 | ||
1004 | /* | 1005 | /* |
1005 | * MMC cards need to have pin 1 high during init. | 1006 | * MMC cards need to have pin 1 high during init. |
1006 | * Init time corresponds rather nicely with the bus mode. | ||
1007 | * It wreaks havoc with the card detection though so | 1007 | * It wreaks havoc with the card detection though so |
1008 | * that needs to be disabed. | 1008 | * that needs to be disabled. |
1009 | */ | 1009 | */ |
1010 | setup = wbsd_read_index(host, WBSD_IDX_SETUP); | 1010 | setup = wbsd_read_index(host, WBSD_IDX_SETUP); |
1011 | if ((ios->power_mode == MMC_POWER_ON) && | 1011 | if (ios->chip_select == MMC_CS_HIGH) |
1012 | (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)) | ||
1013 | { | 1012 | { |
1014 | setup |= WBSD_DAT3_H; | 1013 | setup |= WBSD_DAT3_H; |
1015 | host->flags |= WBSD_FIGNORE_DETECT; | 1014 | host->flags |= WBSD_FIGNORE_DETECT; |
@@ -1017,7 +1016,12 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) | |||
1017 | else | 1016 | else |
1018 | { | 1017 | { |
1019 | setup &= ~WBSD_DAT3_H; | 1018 | setup &= ~WBSD_DAT3_H; |
1020 | host->flags &= ~WBSD_FIGNORE_DETECT; | 1019 | |
1020 | /* | ||
1021 | * We cannot resume card detection immediatly | ||
1022 | * because of capacitance and delays in the chip. | ||
1023 | */ | ||
1024 | mod_timer(&host->ignore_timer, jiffies + HZ/100); | ||
1021 | } | 1025 | } |
1022 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); | 1026 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); |
1023 | 1027 | ||
@@ -1036,6 +1040,31 @@ static struct mmc_host_ops wbsd_ops = { | |||
1036 | \*****************************************************************************/ | 1040 | \*****************************************************************************/ |
1037 | 1041 | ||
1038 | /* | 1042 | /* |
1043 | * Helper function to reset detection ignore | ||
1044 | */ | ||
1045 | |||
1046 | static void wbsd_reset_ignore(unsigned long data) | ||
1047 | { | ||
1048 | struct wbsd_host *host = (struct wbsd_host*)data; | ||
1049 | |||
1050 | BUG_ON(host == NULL); | ||
1051 | |||
1052 | DBG("Resetting card detection ignore\n"); | ||
1053 | |||
1054 | spin_lock_bh(&host->lock); | ||
1055 | |||
1056 | host->flags &= ~WBSD_FIGNORE_DETECT; | ||
1057 | |||
1058 | /* | ||
1059 | * Card status might have changed during the | ||
1060 | * blackout. | ||
1061 | */ | ||
1062 | tasklet_schedule(&host->card_tasklet); | ||
1063 | |||
1064 | spin_unlock_bh(&host->lock); | ||
1065 | } | ||
1066 | |||
1067 | /* | ||
1039 | * Helper function for card detection | 1068 | * Helper function for card detection |
1040 | */ | 1069 | */ |
1041 | static void wbsd_detect_card(unsigned long data) | 1070 | static void wbsd_detect_card(unsigned long data) |
@@ -1097,7 +1126,7 @@ static void wbsd_tasklet_card(unsigned long param) | |||
1097 | * Delay card detection to allow electrical connections | 1126 | * Delay card detection to allow electrical connections |
1098 | * to stabilise. | 1127 | * to stabilise. |
1099 | */ | 1128 | */ |
1100 | mod_timer(&host->timer, jiffies + HZ/2); | 1129 | mod_timer(&host->detect_timer, jiffies + HZ/2); |
1101 | } | 1130 | } |
1102 | 1131 | ||
1103 | spin_unlock(&host->lock); | 1132 | spin_unlock(&host->lock); |
@@ -1124,6 +1153,8 @@ static void wbsd_tasklet_card(unsigned long param) | |||
1124 | 1153 | ||
1125 | mmc_detect_change(host->mmc); | 1154 | mmc_detect_change(host->mmc); |
1126 | } | 1155 | } |
1156 | else | ||
1157 | spin_unlock(&host->lock); | ||
1127 | } | 1158 | } |
1128 | 1159 | ||
1129 | static void wbsd_tasklet_fifo(unsigned long param) | 1160 | static void wbsd_tasklet_fifo(unsigned long param) |
@@ -1328,11 +1359,15 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) | |||
1328 | spin_lock_init(&host->lock); | 1359 | spin_lock_init(&host->lock); |
1329 | 1360 | ||
1330 | /* | 1361 | /* |
1331 | * Set up detection timer | 1362 | * Set up timers |
1332 | */ | 1363 | */ |
1333 | init_timer(&host->timer); | 1364 | init_timer(&host->detect_timer); |
1334 | host->timer.data = (unsigned long)host; | 1365 | host->detect_timer.data = (unsigned long)host; |
1335 | host->timer.function = wbsd_detect_card; | 1366 | host->detect_timer.function = wbsd_detect_card; |
1367 | |||
1368 | init_timer(&host->ignore_timer); | ||
1369 | host->ignore_timer.data = (unsigned long)host; | ||
1370 | host->ignore_timer.function = wbsd_reset_ignore; | ||
1336 | 1371 | ||
1337 | /* | 1372 | /* |
1338 | * Maximum number of segments. Worst case is one sector per segment | 1373 | * Maximum number of segments. Worst case is one sector per segment |
@@ -1370,7 +1405,8 @@ static void __devexit wbsd_free_mmc(struct device* dev) | |||
1370 | host = mmc_priv(mmc); | 1405 | host = mmc_priv(mmc); |
1371 | BUG_ON(host == NULL); | 1406 | BUG_ON(host == NULL); |
1372 | 1407 | ||
1373 | del_timer_sync(&host->timer); | 1408 | del_timer_sync(&host->ignore_timer); |
1409 | del_timer_sync(&host->detect_timer); | ||
1374 | 1410 | ||
1375 | mmc_free_host(mmc); | 1411 | mmc_free_host(mmc); |
1376 | 1412 | ||
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h index 661a9f6a6e6f..8af43549f5d5 100644 --- a/drivers/mmc/wbsd.h +++ b/drivers/mmc/wbsd.h | |||
@@ -181,5 +181,6 @@ struct wbsd_host | |||
181 | struct tasklet_struct finish_tasklet; | 181 | struct tasklet_struct finish_tasklet; |
182 | struct tasklet_struct block_tasklet; | 182 | struct tasklet_struct block_tasklet; |
183 | 183 | ||
184 | struct timer_list timer; /* Card detection timer */ | 184 | struct timer_list detect_timer; /* Card detection timer */ |
185 | struct timer_list ignore_timer; /* Ignore detection timer */ | ||
185 | }; | 186 | }; |
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 9a0893f3249e..30f68c0c8c6e 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -46,6 +46,12 @@ struct mmc_ios { | |||
46 | #define MMC_BUSMODE_OPENDRAIN 1 | 46 | #define MMC_BUSMODE_OPENDRAIN 1 |
47 | #define MMC_BUSMODE_PUSHPULL 2 | 47 | #define MMC_BUSMODE_PUSHPULL 2 |
48 | 48 | ||
49 | unsigned char chip_select; /* SPI chip select */ | ||
50 | |||
51 | #define MMC_CS_DONTCARE 0 | ||
52 | #define MMC_CS_HIGH 1 | ||
53 | #define MMC_CS_LOW 2 | ||
54 | |||
49 | unsigned char power_mode; /* power supply mode */ | 55 | unsigned char power_mode; /* power supply mode */ |
50 | 56 | ||
51 | #define MMC_POWER_OFF 0 | 57 | #define MMC_POWER_OFF 0 |