diff options
-rw-r--r-- | drivers/mmc/wbsd.c | 64 | ||||
-rw-r--r-- | drivers/mmc/wbsd.h | 3 |
2 files changed, 52 insertions, 15 deletions
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 402c2d661fb..08ae22aed9e 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -42,7 +42,7 @@ #include "wbsd.h" #define DRIVER_NAME "wbsd" -#define DRIVER_VERSION "1.3" +#define DRIVER_VERSION "1.4" #ifdef CONFIG_MMC_DEBUG #define DBG(x...) \ @@ -960,8 +960,9 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) struct wbsd_host* host = mmc_priv(mmc); u8 clk, setup, pwr; - DBGF("clock %uHz busmode %u powermode %u Vdd %u\n", - ios->clock, ios->bus_mode, ios->power_mode, ios->vdd); + DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u\n", + ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, + ios->vdd); spin_lock_bh(&host->lock); @@ -1003,13 +1004,11 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) /* * MMC cards need to have pin 1 high during init. - * Init time corresponds rather nicely with the bus mode. * It wreaks havoc with the card detection though so - * that needs to be disabed. + * that needs to be disabled. */ setup = wbsd_read_index(host, WBSD_IDX_SETUP); - if ((ios->power_mode == MMC_POWER_ON) && - (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)) + if (ios->chip_select == MMC_CS_HIGH) { setup |= WBSD_DAT3_H; host->flags |= WBSD_FIGNORE_DETECT; @@ -1017,7 +1016,12 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) else { setup &= ~WBSD_DAT3_H; - host->flags &= ~WBSD_FIGNORE_DETECT; + + /* + * We cannot resume card detection immediatly + * because of capacitance and delays in the chip. + */ + mod_timer(&host->ignore_timer, jiffies + HZ/100); } wbsd_write_index(host, WBSD_IDX_SETUP, setup); @@ -1036,6 +1040,31 @@ static struct mmc_host_ops wbsd_ops = { \*****************************************************************************/ /* + * Helper function to reset detection ignore + */ + +static void wbsd_reset_ignore(unsigned long data) +{ + struct wbsd_host *host = (struct wbsd_host*)data; + + BUG_ON(host == NULL); + + DBG("Resetting card detection ignore\n"); + + spin_lock_bh(&host->lock); + + host->flags &= ~WBSD_FIGNORE_DETECT; + + /* + * Card status might have changed during the + * blackout. + */ + tasklet_schedule(&host->card_tasklet); + + spin_unlock_bh(&host->lock); +} + +/* * Helper function for card detection */ static void wbsd_detect_card(unsigned long data) @@ -1097,7 +1126,7 @@ static void wbsd_tasklet_card(unsigned long param) * Delay card detection to allow electrical connections * to stabilise. */ - mod_timer(&host->timer, jiffies + HZ/2); + mod_timer(&host->detect_timer, jiffies + HZ/2); } spin_unlock(&host->lock); @@ -1124,6 +1153,8 @@ static void wbsd_tasklet_card(unsigned long param) mmc_detect_change(host->mmc); } + else + spin_unlock(&host->lock); } static void wbsd_tasklet_fifo(unsigned long param) @@ -1328,11 +1359,15 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) spin_lock_init(&host->lock); /* - * Set up detection timer + * Set up timers */ - init_timer(&host->timer); - host->timer.data = (unsigned long)host; - host->timer.function = wbsd_detect_card; + init_timer(&host->detect_timer); + host->detect_timer.data = (unsigned long)host; + host->detect_timer.function = wbsd_detect_card; + + init_timer(&host->ignore_timer); + host->ignore_timer.data = (unsigned long)host; + host->ignore_timer.function = wbsd_reset_ignore; /* * Maximum number of segments. Worst case is one sector per segment @@ -1370,7 +1405,8 @@ static void __devexit wbsd_free_mmc(struct device* dev) host = mmc_priv(mmc); BUG_ON(host == NULL); - del_timer_sync(&host->timer); + del_timer_sync(&host->ignore_timer); + del_timer_sync(&host->detect_timer); mmc_free_host(mmc); diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h index 661a9f6a6e6..8af43549f5d 100644 --- a/drivers/mmc/wbsd.h +++ b/drivers/mmc/wbsd.h @@ -181,5 +181,6 @@ struct wbsd_host struct tasklet_struct finish_tasklet; struct tasklet_struct block_tasklet; - struct timer_list timer; /* Card detection timer */ + struct timer_list detect_timer; /* Card detection timer */ + struct timer_list ignore_timer; /* Ignore detection timer */ }; |