diff options
author | David Brownell <david-b@pacbell.net> | 2007-08-08 12:10:23 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2007-09-23 15:39:47 -0400 |
commit | 7213d175e3b6f6db60f843b72e88857a350e146a (patch) | |
tree | 82b5041a4eb51ab734f0d44f16cd9916338c1249 /drivers/mmc/card/block.c | |
parent | 97018580c40c8a31dd7ae744da3378c787a2066d (diff) |
MMC/SD card driver learns SPI
Teaching the MMC/SD block card driver about SPI.
- Provide the SPI response type flags with each request issued.
- Understand that multiblock SPI writes don't use STOP_TRANSMISSION.
- Correct check for APP_CMD failure.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/card/block.c')
-rw-r--r-- | drivers/mmc/card/block.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index ab510689ecde..e38d5a3b2a89 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -151,17 +151,19 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card) | |||
151 | 151 | ||
152 | cmd.opcode = MMC_APP_CMD; | 152 | cmd.opcode = MMC_APP_CMD; |
153 | cmd.arg = card->rca << 16; | 153 | cmd.arg = card->rca << 16; |
154 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | 154 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; |
155 | 155 | ||
156 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | 156 | err = mmc_wait_for_cmd(card->host, &cmd, 0); |
157 | if (err || !(cmd.resp[0] & R1_APP_CMD)) | 157 | if (err) |
158 | return (u32)-1; | ||
159 | if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD)) | ||
158 | return (u32)-1; | 160 | return (u32)-1; |
159 | 161 | ||
160 | memset(&cmd, 0, sizeof(struct mmc_command)); | 162 | memset(&cmd, 0, sizeof(struct mmc_command)); |
161 | 163 | ||
162 | cmd.opcode = SD_APP_SEND_NUM_WR_BLKS; | 164 | cmd.opcode = SD_APP_SEND_NUM_WR_BLKS; |
163 | cmd.arg = 0; | 165 | cmd.arg = 0; |
164 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | 166 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; |
165 | 167 | ||
166 | memset(&data, 0, sizeof(struct mmc_data)); | 168 | memset(&data, 0, sizeof(struct mmc_data)); |
167 | 169 | ||
@@ -220,11 +222,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
220 | brq.cmd.arg = req->sector; | 222 | brq.cmd.arg = req->sector; |
221 | if (!mmc_card_blockaddr(card)) | 223 | if (!mmc_card_blockaddr(card)) |
222 | brq.cmd.arg <<= 9; | 224 | brq.cmd.arg <<= 9; |
223 | brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | 225 | brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; |
224 | brq.data.blksz = 1 << md->block_bits; | 226 | brq.data.blksz = 1 << md->block_bits; |
225 | brq.stop.opcode = MMC_STOP_TRANSMISSION; | 227 | brq.stop.opcode = MMC_STOP_TRANSMISSION; |
226 | brq.stop.arg = 0; | 228 | brq.stop.arg = 0; |
227 | brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC; | 229 | brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; |
228 | brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); | 230 | brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); |
229 | if (brq.data.blocks > card->host->max_blk_count) | 231 | if (brq.data.blocks > card->host->max_blk_count) |
230 | brq.data.blocks = card->host->max_blk_count; | 232 | brq.data.blocks = card->host->max_blk_count; |
@@ -241,7 +243,12 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
241 | brq.data.blocks = 1; | 243 | brq.data.blocks = 1; |
242 | 244 | ||
243 | if (brq.data.blocks > 1) { | 245 | if (brq.data.blocks > 1) { |
244 | brq.mrq.stop = &brq.stop; | 246 | /* SPI multiblock writes terminate using a special |
247 | * token, not a STOP_TRANSMISSION request. | ||
248 | */ | ||
249 | if (!mmc_host_is_spi(card->host) | ||
250 | || rq_data_dir(req) == READ) | ||
251 | brq.mrq.stop = &brq.stop; | ||
245 | readcmd = MMC_READ_MULTIPLE_BLOCK; | 252 | readcmd = MMC_READ_MULTIPLE_BLOCK; |
246 | writecmd = MMC_WRITE_MULTIPLE_BLOCK; | 253 | writecmd = MMC_WRITE_MULTIPLE_BLOCK; |
247 | } else { | 254 | } else { |
@@ -301,7 +308,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
301 | goto cmd_err; | 308 | goto cmd_err; |
302 | } | 309 | } |
303 | 310 | ||
304 | if (rq_data_dir(req) != READ) { | 311 | if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) { |
305 | do { | 312 | do { |
306 | int err; | 313 | int err; |
307 | 314 | ||
@@ -509,7 +516,7 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) | |||
509 | mmc_claim_host(card->host); | 516 | mmc_claim_host(card->host); |
510 | cmd.opcode = MMC_SET_BLOCKLEN; | 517 | cmd.opcode = MMC_SET_BLOCKLEN; |
511 | cmd.arg = 1 << md->block_bits; | 518 | cmd.arg = 1 << md->block_bits; |
512 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | 519 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; |
513 | err = mmc_wait_for_cmd(card->host, &cmd, 5); | 520 | err = mmc_wait_for_cmd(card->host, &cmd, 5); |
514 | mmc_release_host(card->host); | 521 | mmc_release_host(card->host); |
515 | 522 | ||