tree e4148db8d317b895575cb362e208ff17c1150dd0
parent e619524fe5f5b0c13db34ed0f6320d2dcccf6e8d
author Pierre Ossman <[EMAIL PROTECTED]> Wed, 07 Sep 2005 05:18:57 -0700
committer Linus Torvalds <[EMAIL PROTECTED]> Thu, 08 Sep 2005 06:57:51 -0700

[PATCH] mmc: wbsd Secure Digital support

Add support for Secure Digital specific features in the wbsd driver.  Adds
support for read-only switch and wide bus transfers.

Signed-off-by: Pierre Ossman <[EMAIL PROTECTED]>
Cc: Russell King <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>

 drivers/mmc/wbsd.c |   60 +++++++++++++++++++++++++++++++++++++++++++++++------
 drivers/mmc/wbsd.h |    3 ++
 2 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -720,11 +720,28 @@ static void wbsd_prepare_data(struct wbs
         * calculate CRC.
         *
         * Space for CRC must be included in the size.
+        * Two bytes are needed for each data line.
         */
-       blksize = (1 << data->blksz_bits) + 2;
+       if (host->bus_width == MMC_BUS_WIDTH_1)
+       {
+               blksize = (1 << data->blksz_bits) + 2;
+
+               wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
+               wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+       }
+       else if (host->bus_width == MMC_BUS_WIDTH_4)
+       {
+               blksize = (1 << data->blksz_bits) + 2 * 4;
        
-       wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
-       wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+               wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0)
+                       | WBSD_DATA_WIDTH);
+               wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+       }
+       else
+       {
+               data->error = MMC_ERR_INVALID;
+               return;
+       }
 
        /*
         * Clear the FIFO. This is needed even for DMA
@@ -960,9 +977,9 @@ static void wbsd_set_ios(struct mmc_host
        struct wbsd_host* host = mmc_priv(mmc);
        u8 clk, setup, pwr;
        
-       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);
+       DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
+            ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
+            ios->vdd, ios->bus_width);
 
        spin_lock_bh(&host->lock);
 
@@ -1010,6 +1027,7 @@ static void wbsd_set_ios(struct mmc_host
        setup = wbsd_read_index(host, WBSD_IDX_SETUP);
        if (ios->chip_select == MMC_CS_HIGH)
        {
+               BUG_ON(ios->bus_width != MMC_BUS_WIDTH_1);
                setup |= WBSD_DAT3_H;
                host->flags |= WBSD_FIGNORE_DETECT;
        }
@@ -1025,12 +1043,41 @@ static void wbsd_set_ios(struct mmc_host
        }
        wbsd_write_index(host, WBSD_IDX_SETUP, setup);
        
+       /*
+        * Store bus width for later. Will be used when
+        * setting up the data transfer.
+        */
+       host->bus_width = ios->bus_width;
+
        spin_unlock_bh(&host->lock);
 }
 
+static int wbsd_get_ro(struct mmc_host* mmc)
+{
+       struct wbsd_host* host = mmc_priv(mmc);
+       u8 csr;
+
+       spin_lock_bh(&host->lock);
+
+       csr = inb(host->base + WBSD_CSR);
+       csr |= WBSD_MSLED;
+       outb(csr, host->base + WBSD_CSR);
+
+       mdelay(1);
+
+       csr = inb(host->base + WBSD_CSR);
+       csr &= ~WBSD_MSLED;
+       outb(csr, host->base + WBSD_CSR);
+
+       spin_unlock_bh(&host->lock);
+
+       return csr & WBSD_WRPT;
+}
+
 static struct mmc_host_ops wbsd_ops = {
        .request        = wbsd_request,
        .set_ios        = wbsd_set_ios,
+       .get_ro         = wbsd_get_ro,
 };
 
 /*****************************************************************************\
@@ -1355,6 +1402,7 @@ static int __devinit wbsd_alloc_mmc(stru
        mmc->f_min = 375000;
        mmc->f_max = 24000000;
        mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+       mmc->caps = MMC_CAP_4_BIT_DATA;
        
        spin_lock_init(&host->lock);
        
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h
--- a/drivers/mmc/wbsd.h
+++ b/drivers/mmc/wbsd.h
@@ -106,6 +106,8 @@
 #define WBSD_CLK_16M           0x02
 #define WBSD_CLK_24M           0x03
 
+#define WBSD_DATA_WIDTH                0x01
+
 #define WBSD_DAT3_H            0x08
 #define WBSD_FIFO_RESET                0x04
 #define WBSD_SOFT_RESET                0x02
@@ -164,6 +166,7 @@ struct wbsd_host
        int                     firsterr;       /* See fifo functions */
        
        u8                      clk;            /* Current clock speed */
+       unsigned char           bus_width;      /* Current bus width */
        
        int                     config;         /* Config port */
        u8                      unlock_code;    /* Code to unlock config */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to