aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/mmc.c12
-rw-r--r--drivers/mmc/wbsd.c64
-rw-r--r--drivers/mmc/wbsd.h3
-rw-r--r--include/linux/mmc/host.h6
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
1046static 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 */
1041static void wbsd_detect_card(unsigned long data) 1070static 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
1129static void wbsd_tasklet_fifo(unsigned long param) 1160static 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