aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core/sdio_ops.c
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@csr.com>2007-08-08 09:24:21 -0400
committerPierre Ossman <drzeus@drzeus.cx>2007-09-23 15:21:32 -0400
commiteb6594689226663968ef0a9fd71ec5e1e4e04f9c (patch)
treed523962b81a2b5f4a55543d4342daaaebc5d5162 /drivers/mmc/core/sdio_ops.c
parent9a08f82b3cc522f727ace580a2aaee5402435bc8 (diff)
sdio: extend sdio_readsb() and friends to handle any length of buffer
Extend sdio_readsb(), sdio_writesb(), sdio_memcpy_fromio(), and sdio_memcpy_toio() to handle any length of buffer by splitting the transfer into several IO_RW_EXTENDED commands. Typically, a transfer would be split into a single block mode transfer followed by a byte mode transfer for the remainder but we also handle lack of block mode support and the block size being greater than 512 (the maximum byte mode transfer size). host->max_seg_size <= host->max_req_size so there's no need to check both when determining the maximum data size for a single command. Signed-off-by: David Vrabel <david.vrabel@csr.com> Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/core/sdio_ops.c')
-rw-r--r--drivers/mmc/core/sdio_ops.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index 4f2c77139477..98e20532452a 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -88,7 +88,7 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
88} 88}
89 89
90int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, 90int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
91 unsigned addr, int bang, u8 *buf, unsigned size) 91 unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
92{ 92{
93 struct mmc_request mrq; 93 struct mmc_request mrq;
94 struct mmc_command cmd; 94 struct mmc_command cmd;
@@ -97,7 +97,9 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
97 97
98 BUG_ON(!card); 98 BUG_ON(!card);
99 BUG_ON(fn > 7); 99 BUG_ON(fn > 7);
100 BUG_ON(size > 512); 100 BUG_ON(blocks == 1 && blksz > 512);
101 WARN_ON(blocks == 0);
102 WARN_ON(blksz == 0);
101 103
102 memset(&mrq, 0, sizeof(struct mmc_request)); 104 memset(&mrq, 0, sizeof(struct mmc_request));
103 memset(&cmd, 0, sizeof(struct mmc_command)); 105 memset(&cmd, 0, sizeof(struct mmc_command));
@@ -109,18 +111,21 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
109 cmd.opcode = SD_IO_RW_EXTENDED; 111 cmd.opcode = SD_IO_RW_EXTENDED;
110 cmd.arg = write ? 0x80000000 : 0x00000000; 112 cmd.arg = write ? 0x80000000 : 0x00000000;
111 cmd.arg |= fn << 28; 113 cmd.arg |= fn << 28;
112 cmd.arg |= bang ? 0x00000000 : 0x04000000; 114 cmd.arg |= incr_addr ? 0x04000000 : 0x00000000;
113 cmd.arg |= addr << 9; 115 cmd.arg |= addr << 9;
114 cmd.arg |= (size == 512) ? 0 : size; 116 if (blocks == 1 && blksz <= 512)
117 cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */
118 else
119 cmd.arg |= 0x08000000 | blocks; /* block mode */
115 cmd.flags = MMC_RSP_R5 | MMC_CMD_ADTC; 120 cmd.flags = MMC_RSP_R5 | MMC_CMD_ADTC;
116 121
117 data.blksz = size; 122 data.blksz = blksz;
118 data.blocks = 1; 123 data.blocks = blocks;
119 data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; 124 data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
120 data.sg = &sg; 125 data.sg = &sg;
121 data.sg_len = 1; 126 data.sg_len = 1;
122 127
123 sg_init_one(&sg, buf, size); 128 sg_init_one(&sg, buf, blksz * blocks);
124 129
125 mmc_set_data_timeout(&data, card); 130 mmc_set_data_timeout(&data, card);
126 131