Loading drivers/mmc/core/sdio_io.c +184 −0 Original line number Diff line number Diff line Loading @@ -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); drivers/mmc/core/sdio_ops.c +57 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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; } drivers/mmc/core/sdio_ops.h +2 −0 Original line number Diff line number Diff line Loading @@ -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 include/linux/mmc/sdio.h +12 −0 Original line number Diff line number Diff line Loading @@ -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: Loading @@ -26,6 +27,17 @@ * [7:0] Data */ /* * 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 Loading include/linux/mmc/sdio_func.h +20 −0 Original line number Diff line number Diff line Loading @@ -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; }; Loading Loading @@ -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 Loading
drivers/mmc/core/sdio_io.c +184 −0 Original line number Diff line number Diff line Loading @@ -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);
drivers/mmc/core/sdio_ops.c +57 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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; }
drivers/mmc/core/sdio_ops.h +2 −0 Original line number Diff line number Diff line Loading @@ -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
include/linux/mmc/sdio.h +12 −0 Original line number Diff line number Diff line Loading @@ -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: Loading @@ -26,6 +27,17 @@ * [7:0] Data */ /* * 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 Loading
include/linux/mmc/sdio_func.h +20 −0 Original line number Diff line number Diff line Loading @@ -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; }; Loading Loading @@ -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