Merge master.kernel.org:/home/rmk/linux-2.6-mmc
authorLinus Torvalds <torvalds@evo.osdl.org>
Mon, 5 Sep 2005 07:18:09 +0000 (00:18 -0700)
committerLinus Torvalds <torvalds@evo.osdl.org>
Mon, 5 Sep 2005 07:18:09 +0000 (00:18 -0700)
drivers/mmc/mmc.c
drivers/mmc/wbsd.c
drivers/mmc/wbsd.h
include/linux/mmc/host.h

index 3c5904834fe8289db5672fae41a543d9bc7c6059..0a8165974ba763abebeb0519434f849ea8876413 100644 (file)
@@ -457,6 +457,11 @@ static void mmc_idle_cards(struct mmc_host *host)
 {
        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.arg = 0;
        cmd.flags = MMC_RSP_NONE;
@@ -464,6 +469,11 @@ static void mmc_idle_cards(struct mmc_host *host)
        mmc_wait_for_cmd(host, &cmd, 0);
 
        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)
 
        host->ios.vdd = bit;
        host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+       host->ios.chip_select = MMC_CS_DONTCARE;
        host->ios.power_mode = MMC_POWER_UP;
        host->ops->set_ios(host, &host->ios);
 
@@ -492,6 +503,7 @@ static void mmc_power_off(struct mmc_host *host)
        host->ios.clock = 0;
        host->ios.vdd = 0;
        host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+       host->ios.chip_select = MMC_CS_DONTCARE;
        host->ios.power_mode = MMC_POWER_OFF;
        host->ops->set_ios(host, &host->ios);
 }
index 402c2d661fb2814d06983d6a6f0e3c89c110e89f..08ae22aed9e8f7f38a1c61af4a0b87b92b563a0b 100644 (file)
@@ -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);
        
@@ -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
  */
@@ -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);
        
index 661a9f6a6e6ff5b63cfc423f1bd203fa5b1eb614..8af43549f5d5b95b34bbe8b17b1fad18199be236 100644 (file)
@@ -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 */
 };
index 9a0893f3249e8b2869d24c6e52e7c1799c8ff7bb..30f68c0c8c6ebfa5b3c2cfe9b51aca76c86159fa 100644 (file)
@@ -46,6 +46,12 @@ struct mmc_ios {
 #define MMC_BUSMODE_OPENDRAIN  1
 #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 */
 
 #define MMC_POWER_OFF          0