Commit da1f136c authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/home/rmk/linux-2.6-mmc

parents 64c4813d 1656fa57
...@@ -457,6 +457,11 @@ static void mmc_idle_cards(struct mmc_host *host) ...@@ -457,6 +457,11 @@ static void mmc_idle_cards(struct mmc_host *host)
{ {
struct mmc_command cmd; struct mmc_command cmd;
host->ios.chip_select = MMC_CS_HIGH;
host->ops->set_ios(host, &host->ios);
mmc_delay(1);
cmd.opcode = MMC_GO_IDLE_STATE; cmd.opcode = MMC_GO_IDLE_STATE;
cmd.arg = 0; cmd.arg = 0;
cmd.flags = MMC_RSP_NONE; cmd.flags = MMC_RSP_NONE;
...@@ -464,6 +469,11 @@ static void mmc_idle_cards(struct mmc_host *host) ...@@ -464,6 +469,11 @@ static void mmc_idle_cards(struct mmc_host *host)
mmc_wait_for_cmd(host, &cmd, 0); mmc_wait_for_cmd(host, &cmd, 0);
mmc_delay(1); mmc_delay(1);
host->ios.chip_select = MMC_CS_DONTCARE;
host->ops->set_ios(host, &host->ios);
mmc_delay(1);
} }
/* /*
...@@ -475,6 +485,7 @@ static void mmc_power_up(struct mmc_host *host) ...@@ -475,6 +485,7 @@ static void mmc_power_up(struct mmc_host *host)
host->ios.vdd = bit; host->ios.vdd = bit;
host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
host->ios.chip_select = MMC_CS_DONTCARE;
host->ios.power_mode = MMC_POWER_UP; host->ios.power_mode = MMC_POWER_UP;
host->ops->set_ios(host, &host->ios); host->ops->set_ios(host, &host->ios);
...@@ -492,6 +503,7 @@ static void mmc_power_off(struct mmc_host *host) ...@@ -492,6 +503,7 @@ static void mmc_power_off(struct mmc_host *host)
host->ios.clock = 0; host->ios.clock = 0;
host->ios.vdd = 0; host->ios.vdd = 0;
host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
host->ios.chip_select = MMC_CS_DONTCARE;
host->ios.power_mode = MMC_POWER_OFF; host->ios.power_mode = MMC_POWER_OFF;
host->ops->set_ios(host, &host->ios); host->ops->set_ios(host, &host->ios);
} }
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#include "wbsd.h" #include "wbsd.h"
#define DRIVER_NAME "wbsd" #define DRIVER_NAME "wbsd"
#define DRIVER_VERSION "1.3" #define DRIVER_VERSION "1.4"
#ifdef CONFIG_MMC_DEBUG #ifdef CONFIG_MMC_DEBUG
#define DBG(x...) \ #define DBG(x...) \
...@@ -960,8 +960,9 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) ...@@ -960,8 +960,9 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
struct wbsd_host* host = mmc_priv(mmc); struct wbsd_host* host = mmc_priv(mmc);
u8 clk, setup, pwr; u8 clk, setup, pwr;
DBGF("clock %uHz busmode %u powermode %u Vdd %u\n", DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u\n",
ios->clock, ios->bus_mode, ios->power_mode, ios->vdd); ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
ios->vdd);
spin_lock_bh(&host->lock); spin_lock_bh(&host->lock);
...@@ -1003,13 +1004,11 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) ...@@ -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. * 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 * 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); setup = wbsd_read_index(host, WBSD_IDX_SETUP);
if ((ios->power_mode == MMC_POWER_ON) && if (ios->chip_select == MMC_CS_HIGH)
(ios->bus_mode == MMC_BUSMODE_OPENDRAIN))
{ {
setup |= WBSD_DAT3_H; setup |= WBSD_DAT3_H;
host->flags |= WBSD_FIGNORE_DETECT; host->flags |= WBSD_FIGNORE_DETECT;
...@@ -1017,7 +1016,12 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) ...@@ -1017,7 +1016,12 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
else else
{ {
setup &= ~WBSD_DAT3_H; 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); wbsd_write_index(host, WBSD_IDX_SETUP, setup);
...@@ -1035,6 +1039,31 @@ static struct mmc_host_ops wbsd_ops = { ...@@ -1035,6 +1039,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 * Helper function for card detection
*/ */
...@@ -1097,7 +1126,7 @@ static void wbsd_tasklet_card(unsigned long param) ...@@ -1097,7 +1126,7 @@ static void wbsd_tasklet_card(unsigned long param)
* Delay card detection to allow electrical connections * Delay card detection to allow electrical connections
* to stabilise. * to stabilise.
*/ */
mod_timer(&host->timer, jiffies + HZ/2); mod_timer(&host->detect_timer, jiffies + HZ/2);
} }
spin_unlock(&host->lock); spin_unlock(&host->lock);
...@@ -1124,6 +1153,8 @@ static void wbsd_tasklet_card(unsigned long param) ...@@ -1124,6 +1153,8 @@ static void wbsd_tasklet_card(unsigned long param)
mmc_detect_change(host->mmc); mmc_detect_change(host->mmc);
} }
else
spin_unlock(&host->lock);
} }
static void wbsd_tasklet_fifo(unsigned long param) static void wbsd_tasklet_fifo(unsigned long param)
...@@ -1328,11 +1359,15 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) ...@@ -1328,11 +1359,15 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
spin_lock_init(&host->lock); spin_lock_init(&host->lock);
/* /*
* Set up detection timer * Set up timers
*/ */
init_timer(&host->timer); init_timer(&host->detect_timer);
host->timer.data = (unsigned long)host; host->detect_timer.data = (unsigned long)host;
host->timer.function = wbsd_detect_card; 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 * 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,7 +1405,8 @@ static void __devexit wbsd_free_mmc(struct device* dev)
host = mmc_priv(mmc); host = mmc_priv(mmc);
BUG_ON(host == NULL); 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); mmc_free_host(mmc);
......
...@@ -181,5 +181,6 @@ struct wbsd_host ...@@ -181,5 +181,6 @@ struct wbsd_host
struct tasklet_struct finish_tasklet; struct tasklet_struct finish_tasklet;
struct tasklet_struct block_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 */
}; };
...@@ -46,6 +46,12 @@ struct mmc_ios { ...@@ -46,6 +46,12 @@ struct mmc_ios {
#define MMC_BUSMODE_OPENDRAIN 1 #define MMC_BUSMODE_OPENDRAIN 1
#define MMC_BUSMODE_PUSHPULL 2 #define MMC_BUSMODE_PUSHPULL 2
unsigned char chip_select; /* SPI chip select */
#define MMC_CS_DONTCARE 0
#define MMC_CS_HIGH 1
#define MMC_CS_LOW 2
unsigned char power_mode; /* power supply mode */ unsigned char power_mode; /* power supply mode */
#define MMC_POWER_OFF 0 #define MMC_POWER_OFF 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment