Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=112c9db91ee6bf19eca7cbb6854be3127381c229
Commit:     112c9db91ee6bf19eca7cbb6854be3127381c229
Parent:     5ed334a1f8caaae98806d572f78c5802975ea20f
Author:     Pierre Ossman <[EMAIL PROTECTED]>
AuthorDate: Fri Jul 6 13:35:01 2007 +0200
Committer:  Pierre Ossman <[EMAIL PROTECTED]>
CommitDate: Sun Sep 23 21:09:34 2007 +0200

    sdio: support IO_RW_EXTENDED
    
    Support the multi-byte transfer operation, including handlers for
    common operations like writel()/readl().
    
    Signed-off-by: Pierre Ossman <[EMAIL PROTECTED]>
---
 drivers/mmc/core/sdio_io.c    |  184 +++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/core/sdio_ops.c   |   57 +++++++++++++
 drivers/mmc/core/sdio_ops.h   |    2 +
 include/linux/mmc/sdio.h      |   12 +++
 include/linux/mmc/sdio_func.h |   20 +++++
 5 files changed, 275 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index eb6c209..ecdb772 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -196,3 +196,187 @@ void sdio_writeb(struct sdio_func *func, unsigned char b, 
unsigned int addr,
 }
 EXPORT_SYMBOL_GPL(sdio_writeb);
 
+/**
+ *     sdio_memcpy_fromio - read a chunk of memory from a SDIO function
+ *     @func: SDIO function to access
+ *     @dst: buffer to store the data
+ *     @addr: address to begin reading from
+ *     @count: number of bytes to read
+ *
+ *     Reads up to 512 bytes from the address space of a given SDIO
+ *     function. Return value indicates if the transfer succeeded or
+ *     not.
+ */
+int sdio_memcpy_fromio(struct sdio_func *func, void *dst,
+       unsigned int addr, int count)
+{
+       return mmc_io_rw_extended(func->card, 0, func->num, addr, 0, dst,
+               count);
+}
+EXPORT_SYMBOL_GPL(sdio_memcpy_fromio);
+
+/**
+ *     sdio_memcpy_toio - write a chunk of memory to a SDIO function
+ *     @func: SDIO function to access
+ *     @addr: address to start writing to
+ *     @src: buffer that contains the data to write
+ *     @count: number of bytes to write
+ *
+ *     Writes up to 512 bytes to the address space of a given SDIO
+ *     function. Return value indicates if the transfer succeeded or
+ *     not.
+ */
+int sdio_memcpy_toio(struct sdio_func *func, unsigned int addr,
+       void *src, int count)
+{
+       return mmc_io_rw_extended(func->card, 1, func->num, addr, 0, src,
+               count);
+}
+EXPORT_SYMBOL_GPL(sdio_memcpy_toio);
+
+/**
+ *     sdio_readsb - read from a FIFO on a SDIO function
+ *     @func: SDIO function to access
+ *     @dst: buffer to store the data
+ *     @addr: address of (single byte) FIFO
+ *     @count: number of bytes to read
+ *
+ *     Reads up to 512 bytes from the specified FIFO of a given SDIO
+ *     function. Return value indicates if the transfer succeeded or
+ *     not.
+ */
+int sdio_readsb(struct sdio_func *func, void *dst, unsigned int addr,
+       int count)
+{
+       return mmc_io_rw_extended(func->card, 0, func->num, addr, 1, dst,
+               count);
+}
+
+EXPORT_SYMBOL_GPL(sdio_readsb);
+
+/**
+ *     sdio_writesb - write to a FIFO of a SDIO function
+ *     @func: SDIO function to access
+ *     @addr: address of (single byte) FIFO
+ *     @src: buffer that contains the data to write
+ *     @count: number of bytes to write
+ *
+ *     Writes up to 512 bytes to the specified FIFO of a given SDIO
+ *     function. Return value indicates if the transfer succeeded or
+ *     not.
+ */
+int sdio_writesb(struct sdio_func *func, unsigned int addr, void *src,
+       int count)
+{
+       return mmc_io_rw_extended(func->card, 1, func->num, addr, 1, src,
+               count);
+}
+EXPORT_SYMBOL_GPL(sdio_writesb);
+
+/**
+ *     sdio_readw - read a 16 bit integer from a SDIO function
+ *     @func: SDIO function to access
+ *     @addr: address to read
+ *     @err_ret: optional status value from transfer
+ *
+ *     Reads a 16 bit integer from the address space of a given SDIO
+ *     function. If there is a problem reading the address, 0xffff
+ *     is returned and @err_ret will contain the error code.
+ */
+unsigned short sdio_readw(struct sdio_func *func, unsigned int addr,
+       int *err_ret)
+{
+       int ret;
+
+       if (err_ret)
+               *err_ret = 0;
+
+       ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 2);
+       if (ret) {
+               if (err_ret)
+                       *err_ret = ret;
+               return 0xFFFF;
+       }
+
+       return le16_to_cpu(*(u16*)func->tmpbuf);
+}
+EXPORT_SYMBOL_GPL(sdio_readw);
+
+/**
+ *     sdio_writew - write a 16 bit integer to a SDIO function
+ *     @func: SDIO function to access
+ *     @b: integer to write
+ *     @addr: address to write to
+ *     @err_ret: optional status value from transfer
+ *
+ *     Writes a 16 bit integer to the address space of a given SDIO
+ *     function. @err_ret will contain the status of the actual
+ *     transfer.
+ */
+void sdio_writew(struct sdio_func *func, unsigned short b, unsigned int addr,
+       int *err_ret)
+{
+       int ret;
+
+       *(u16*)func->tmpbuf = cpu_to_le16(b);
+
+       ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 2);
+       if (err_ret)
+               *err_ret = ret;
+}
+EXPORT_SYMBOL_GPL(sdio_writew);
+
+/**
+ *     sdio_readl - read a 32 bit integer from a SDIO function
+ *     @func: SDIO function to access
+ *     @addr: address to read
+ *     @err_ret: optional status value from transfer
+ *
+ *     Reads a 32 bit integer from the address space of a given SDIO
+ *     function. If there is a problem reading the address,
+ *     0xffffffff is returned and @err_ret will contain the error
+ *     code.
+ */
+unsigned long sdio_readl(struct sdio_func *func, unsigned int addr,
+       int *err_ret)
+{
+       int ret;
+
+       if (err_ret)
+               *err_ret = 0;
+
+       ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 4);
+       if (ret) {
+               if (err_ret)
+                       *err_ret = ret;
+               return 0xFFFFFFFF;
+       }
+
+       return le32_to_cpu(*(u32*)func->tmpbuf);
+}
+EXPORT_SYMBOL_GPL(sdio_readl);
+
+/**
+ *     sdio_writel - write a 32 bit integer to a SDIO function
+ *     @func: SDIO function to access
+ *     @b: integer to write
+ *     @addr: address to write to
+ *     @err_ret: optional status value from transfer
+ *
+ *     Writes a 32 bit integer to the address space of a given SDIO
+ *     function. @err_ret will contain the status of the actual
+ *     transfer.
+ */
+void sdio_writel(struct sdio_func *func, unsigned long b, unsigned int addr,
+       int *err_ret)
+{
+       int ret;
+
+       *(u32*)func->tmpbuf = cpu_to_le32(b);
+
+       ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 4);
+       if (err_ret)
+               *err_ret = ret;
+}
+EXPORT_SYMBOL_GPL(sdio_writel);
+
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index 31233f7..4f2c771 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -9,6 +9,9 @@
  * your option) any later version.
  */
 
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/mmc.h>
@@ -84,3 +87,57 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, 
unsigned fn,
        return 0;
 }
 
+int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
+       unsigned addr, int bang, u8 *buf, unsigned size)
+{
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+       struct scatterlist sg;
+
+       BUG_ON(!card);
+       BUG_ON(fn > 7);
+       BUG_ON(size > 512);
+
+       memset(&mrq, 0, sizeof(struct mmc_request));
+       memset(&cmd, 0, sizeof(struct mmc_command));
+       memset(&data, 0, sizeof(struct mmc_data));
+
+       mrq.cmd = &cmd;
+       mrq.data = &data;
+
+       cmd.opcode = SD_IO_RW_EXTENDED;
+       cmd.arg = write ? 0x80000000 : 0x00000000;
+       cmd.arg |= fn << 28;
+       cmd.arg |= bang ? 0x00000000 : 0x04000000;
+       cmd.arg |= addr << 9;
+       cmd.arg |= (size == 512) ? 0 : size;
+       cmd.flags = MMC_RSP_R5 | MMC_CMD_ADTC;
+
+       data.blksz = size;
+       data.blocks = 1;
+       data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
+       data.sg = &sg;
+       data.sg_len = 1;
+
+       sg_init_one(&sg, buf, size);
+
+       mmc_set_data_timeout(&data, card);
+
+       mmc_wait_for_req(card->host, &mrq);
+
+       if (cmd.error)
+               return cmd.error;
+       if (data.error)
+               return data.error;
+
+       if (cmd.resp[0] & R5_ERROR)
+               return -EIO;
+       if (cmd.resp[0] & R5_FUNCTION_NUMBER)
+               return -EINVAL;
+       if (cmd.resp[0] & R5_OUT_OF_RANGE)
+               return -ERANGE;
+
+       return 0;
+}
+
diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h
index f0e9d69..1d42e4f 100644
--- a/drivers/mmc/core/sdio_ops.h
+++ b/drivers/mmc/core/sdio_ops.h
@@ -15,6 +15,8 @@
 int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
 int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
        unsigned addr, u8 in, u8* out);
+int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
+       unsigned addr, int bang, u8 *data, unsigned size);
 
 #endif
 
diff --git a/include/linux/mmc/sdio.h b/include/linux/mmc/sdio.h
index 56239f4..9b1ec76 100644
--- a/include/linux/mmc/sdio.h
+++ b/include/linux/mmc/sdio.h
@@ -15,6 +15,7 @@
 /* SDIO commands                         type  argument     response */
 #define SD_IO_SEND_OP_COND          5 /* bcr  [23:0] OCR         R4  */
 #define SD_IO_RW_DIRECT            52 /* ac   [31:0] See below   R5  */
+#define SD_IO_RW_EXTENDED          53 /* adtc [31:0] See below   R5  */
 
 /*
  * SD_IO_RW_DIRECT argument format:
@@ -27,6 +28,17 @@
  */
 
 /*
+ * SD_IO_RW_EXTENDED argument format:
+ *
+ *      [31] R/W flag
+ *      [30:28] Function number
+ *      [27] Block mode
+ *      [26] Increment address
+ *      [25:9] Register address
+ *      [8:0] Byte/block count
+ */
+
+/*
   SDIO status in R5
   Type
        e : error bit
diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
index a8d268c..af813ff 100644
--- a/include/linux/mmc/sdio_func.h
+++ b/include/linux/mmc/sdio_func.h
@@ -48,6 +48,8 @@ struct sdio_func {
        unsigned int            state;          /* function state */
 #define SDIO_STATE_PRESENT     (1<<0)          /* present in sysfs */
 
+       u8                      tmpbuf[4];      /* DMA:able scratch buffer */
+
        struct sdio_func_tuple *tuples;
 };
 
@@ -114,9 +116,27 @@ extern int sdio_release_irq(struct sdio_func *func);
 
 extern unsigned char sdio_readb(struct sdio_func *func,
        unsigned int addr, int *err_ret);
+extern unsigned short sdio_readw(struct sdio_func *func,
+       unsigned int addr, int *err_ret);
+extern unsigned long sdio_readl(struct sdio_func *func,
+       unsigned int addr, int *err_ret);
+
+extern int sdio_memcpy_fromio(struct sdio_func *func, void *dst,
+       unsigned int addr, int count);
+extern int sdio_readsb(struct sdio_func *func, void *dst,
+       unsigned int addr, int count);
 
 extern void sdio_writeb(struct sdio_func *func, unsigned char b,
        unsigned int addr, int *err_ret);
+extern void sdio_writew(struct sdio_func *func, unsigned short b,
+       unsigned int addr, int *err_ret);
+extern void sdio_writel(struct sdio_func *func, unsigned long b,
+       unsigned int addr, int *err_ret);
+
+extern int sdio_memcpy_toio(struct sdio_func *func, unsigned int addr,
+       void *src, int count);
+extern int sdio_writesb(struct sdio_func *func, unsigned int addr,
+       void *src, int count);
 
 #endif
 
-
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