diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-11 10:56:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-11 10:56:38 -0400 |
commit | e004876c3b0b6a71406069b0e55368cb9bbdc920 (patch) | |
tree | 43f95e14b282cbc683ec66539de25e0e94649f65 | |
parent | 5a05e5bf204e729b79e9462785f2fa09d5126855 (diff) | |
parent | 6fe9febb8af2f82f9caace1aa1c00cd8de7469ac (diff) |
Merge master.kernel.org:/home/rmk/linux-2.6-mmc
* master.kernel.org:/home/rmk/linux-2.6-mmc:
[MMC] Always use a sector size of 512 bytes
[MMC] Cleanup 385e3227d4d83ab13d7767c4bb3593b0256bf246
[ARM] 3751/1: i.MX/MX1 SD/MMC use 512 bytes request for SCR read
[MMC] Fix SD timeout calculation
[MMC] constify mmc_host_ops
-rw-r--r-- | drivers/mmc/imxmmc.c | 69 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 55 | ||||
-rw-r--r-- | drivers/mmc/mmc_block.c | 60 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 2 | ||||
-rw-r--r-- | include/linux/mmc/mmc.h | 2 |
5 files changed, 96 insertions, 92 deletions
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c index 7ca9e95bdf89..fb6565b98f32 100644 --- a/drivers/mmc/imxmmc.c +++ b/drivers/mmc/imxmmc.c | |||
@@ -91,6 +91,8 @@ struct imxmci_host { | |||
91 | int dma_allocated; | 91 | int dma_allocated; |
92 | 92 | ||
93 | unsigned char actual_bus_width; | 93 | unsigned char actual_bus_width; |
94 | |||
95 | int prev_cmd_code; | ||
94 | }; | 96 | }; |
95 | 97 | ||
96 | #define IMXMCI_PEND_IRQ_b 0 | 98 | #define IMXMCI_PEND_IRQ_b 0 |
@@ -248,16 +250,14 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) | |||
248 | * partial FIFO fills and reads. The length has to be rounded up to burst size multiple. | 250 | * partial FIFO fills and reads. The length has to be rounded up to burst size multiple. |
249 | * This is required for SCR read at least. | 251 | * This is required for SCR read at least. |
250 | */ | 252 | */ |
251 | if (datasz < 64) { | 253 | if (datasz < 512) { |
252 | host->dma_size = datasz; | 254 | host->dma_size = datasz; |
253 | if (data->flags & MMC_DATA_READ) { | 255 | if (data->flags & MMC_DATA_READ) { |
254 | host->dma_dir = DMA_FROM_DEVICE; | 256 | host->dma_dir = DMA_FROM_DEVICE; |
255 | 257 | ||
256 | /* Hack to enable read SCR */ | 258 | /* Hack to enable read SCR */ |
257 | if(datasz < 16) { | 259 | MMC_NOB = 1; |
258 | MMC_NOB = 1; | 260 | MMC_BLK_LEN = 512; |
259 | MMC_BLK_LEN = 16; | ||
260 | } | ||
261 | } else { | 261 | } else { |
262 | host->dma_dir = DMA_TO_DEVICE; | 262 | host->dma_dir = DMA_TO_DEVICE; |
263 | } | 263 | } |
@@ -409,6 +409,9 @@ static void imxmci_finish_request(struct imxmci_host *host, struct mmc_request * | |||
409 | 409 | ||
410 | spin_unlock_irqrestore(&host->lock, flags); | 410 | spin_unlock_irqrestore(&host->lock, flags); |
411 | 411 | ||
412 | if(req && req->cmd) | ||
413 | host->prev_cmd_code = req->cmd->opcode; | ||
414 | |||
412 | host->req = NULL; | 415 | host->req = NULL; |
413 | host->cmd = NULL; | 416 | host->cmd = NULL; |
414 | host->data = NULL; | 417 | host->data = NULL; |
@@ -553,7 +556,6 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) | |||
553 | { | 556 | { |
554 | int i; | 557 | int i; |
555 | int burst_len; | 558 | int burst_len; |
556 | int flush_len; | ||
557 | int trans_done = 0; | 559 | int trans_done = 0; |
558 | unsigned int stat = *pstat; | 560 | unsigned int stat = *pstat; |
559 | 561 | ||
@@ -566,44 +568,43 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) | |||
566 | dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n", | 568 | dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n", |
567 | stat); | 569 | stat); |
568 | 570 | ||
571 | udelay(20); /* required for clocks < 8MHz*/ | ||
572 | |||
569 | if(host->dma_dir == DMA_FROM_DEVICE) { | 573 | if(host->dma_dir == DMA_FROM_DEVICE) { |
570 | imxmci_busy_wait_for_status(host, &stat, | 574 | imxmci_busy_wait_for_status(host, &stat, |
571 | STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE, | 575 | STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE, |
572 | 20, "imxmci_cpu_driven_data read"); | 576 | 50, "imxmci_cpu_driven_data read"); |
573 | 577 | ||
574 | while((stat & (STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE)) && | 578 | while((stat & (STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE)) && |
575 | (host->data_cnt < host->dma_size)) { | 579 | (host->data_cnt < 512)) { |
576 | if(burst_len >= host->dma_size - host->data_cnt) { | 580 | |
577 | flush_len = burst_len; | 581 | udelay(20); /* required for clocks < 8MHz*/ |
578 | burst_len = host->dma_size - host->data_cnt; | ||
579 | flush_len -= burst_len; | ||
580 | host->data_cnt = host->dma_size; | ||
581 | trans_done = 1; | ||
582 | } else { | ||
583 | flush_len = 0; | ||
584 | host->data_cnt += burst_len; | ||
585 | } | ||
586 | 582 | ||
587 | for(i = burst_len; i>=2 ; i-=2) { | 583 | for(i = burst_len; i>=2 ; i-=2) { |
588 | *(host->data_ptr++) = MMC_BUFFER_ACCESS; | 584 | u16 data; |
589 | udelay(20); /* required for clocks < 8MHz*/ | 585 | data = MMC_BUFFER_ACCESS; |
586 | udelay(10); /* required for clocks < 8MHz*/ | ||
587 | if(host->data_cnt+2 <= host->dma_size) { | ||
588 | *(host->data_ptr++) = data; | ||
589 | } else { | ||
590 | if(host->data_cnt < host->dma_size) | ||
591 | *(u8*)(host->data_ptr) = data; | ||
592 | } | ||
593 | host->data_cnt += 2; | ||
590 | } | 594 | } |
591 | 595 | ||
592 | if(i == 1) | ||
593 | *(u8*)(host->data_ptr) = MMC_BUFFER_ACCESS; | ||
594 | |||
595 | stat = MMC_STATUS; | 596 | stat = MMC_STATUS; |
596 | 597 | ||
597 | /* Flush extra bytes from FIFO */ | 598 | dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read %d burst %d STATUS = 0x%x\n", |
598 | while(flush_len && !(stat & STATUS_DATA_TRANS_DONE)){ | 599 | host->data_cnt, burst_len, stat); |
599 | i = MMC_BUFFER_ACCESS; | ||
600 | stat = MMC_STATUS; | ||
601 | stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */ | ||
602 | } | ||
603 | |||
604 | dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read burst %d STATUS = 0x%x\n", | ||
605 | burst_len, stat); | ||
606 | } | 600 | } |
601 | |||
602 | if((stat & STATUS_DATA_TRANS_DONE) && (host->data_cnt >= 512)) | ||
603 | trans_done = 1; | ||
604 | |||
605 | if(host->dma_size & 0x1ff) | ||
606 | stat &= ~STATUS_CRC_READ_ERR; | ||
607 | |||
607 | } else { | 608 | } else { |
608 | imxmci_busy_wait_for_status(host, &stat, | 609 | imxmci_busy_wait_for_status(host, &stat, |
609 | STATUS_APPL_BUFF_FE, | 610 | STATUS_APPL_BUFF_FE, |
@@ -692,8 +693,8 @@ static void imxmci_tasklet_fnc(unsigned long data) | |||
692 | what, stat, MMC_INT_MASK); | 693 | what, stat, MMC_INT_MASK); |
693 | dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n", | 694 | dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n", |
694 | MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma)); | 695 | MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma)); |
695 | dev_err(mmc_dev(host->mmc), "CMD%d, bus %d-bit, dma_size = 0x%x\n", | 696 | dev_err(mmc_dev(host->mmc), "CMD%d, prevCMD%d, bus %d-bit, dma_size = 0x%x\n", |
696 | host->cmd?host->cmd->opcode:0, 1<<host->actual_bus_width, host->dma_size); | 697 | host->cmd?host->cmd->opcode:0, host->prev_cmd_code, 1<<host->actual_bus_width, host->dma_size); |
697 | } | 698 | } |
698 | 699 | ||
699 | if(!host->present || timeout) | 700 | if(!host->present || timeout) |
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 33525bdf2ab6..74eaaee66de0 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c | |||
@@ -247,6 +247,55 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca, | |||
247 | 247 | ||
248 | EXPORT_SYMBOL(mmc_wait_for_app_cmd); | 248 | EXPORT_SYMBOL(mmc_wait_for_app_cmd); |
249 | 249 | ||
250 | /** | ||
251 | * mmc_set_data_timeout - set the timeout for a data command | ||
252 | * @data: data phase for command | ||
253 | * @card: the MMC card associated with the data transfer | ||
254 | * @write: flag to differentiate reads from writes | ||
255 | */ | ||
256 | void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card, | ||
257 | int write) | ||
258 | { | ||
259 | unsigned int mult; | ||
260 | |||
261 | /* | ||
262 | * SD cards use a 100 multiplier rather than 10 | ||
263 | */ | ||
264 | mult = mmc_card_sd(card) ? 100 : 10; | ||
265 | |||
266 | /* | ||
267 | * Scale up the multiplier (and therefore the timeout) by | ||
268 | * the r2w factor for writes. | ||
269 | */ | ||
270 | if (write) | ||
271 | mult <<= card->csd.r2w_factor; | ||
272 | |||
273 | data->timeout_ns = card->csd.tacc_ns * mult; | ||
274 | data->timeout_clks = card->csd.tacc_clks * mult; | ||
275 | |||
276 | /* | ||
277 | * SD cards also have an upper limit on the timeout. | ||
278 | */ | ||
279 | if (mmc_card_sd(card)) { | ||
280 | unsigned int timeout_us, limit_us; | ||
281 | |||
282 | timeout_us = data->timeout_ns / 1000; | ||
283 | timeout_us += data->timeout_clks * 1000 / | ||
284 | (card->host->ios.clock / 1000); | ||
285 | |||
286 | if (write) | ||
287 | limit_us = 250000; | ||
288 | else | ||
289 | limit_us = 100000; | ||
290 | |||
291 | if (timeout_us > limit_us) { | ||
292 | data->timeout_ns = limit_us * 1000; | ||
293 | data->timeout_clks = 0; | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | EXPORT_SYMBOL(mmc_set_data_timeout); | ||
298 | |||
250 | static int mmc_select_card(struct mmc_host *host, struct mmc_card *card); | 299 | static int mmc_select_card(struct mmc_host *host, struct mmc_card *card); |
251 | 300 | ||
252 | /** | 301 | /** |
@@ -908,11 +957,9 @@ static void mmc_read_scrs(struct mmc_host *host) | |||
908 | { | 957 | { |
909 | int err; | 958 | int err; |
910 | struct mmc_card *card; | 959 | struct mmc_card *card; |
911 | |||
912 | struct mmc_request mrq; | 960 | struct mmc_request mrq; |
913 | struct mmc_command cmd; | 961 | struct mmc_command cmd; |
914 | struct mmc_data data; | 962 | struct mmc_data data; |
915 | |||
916 | struct scatterlist sg; | 963 | struct scatterlist sg; |
917 | 964 | ||
918 | list_for_each_entry(card, &host->cards, node) { | 965 | list_for_each_entry(card, &host->cards, node) { |
@@ -947,8 +994,8 @@ static void mmc_read_scrs(struct mmc_host *host) | |||
947 | 994 | ||
948 | memset(&data, 0, sizeof(struct mmc_data)); | 995 | memset(&data, 0, sizeof(struct mmc_data)); |
949 | 996 | ||
950 | data.timeout_ns = card->csd.tacc_ns * 10; | 997 | mmc_set_data_timeout(&data, card, 0); |
951 | data.timeout_clks = card->csd.tacc_clks * 10; | 998 | |
952 | data.blksz_bits = 3; | 999 | data.blksz_bits = 3; |
953 | data.blksz = 1 << 3; | 1000 | data.blksz = 1 << 3; |
954 | data.blocks = 1; | 1001 | data.blocks = 1; |
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index 115cc21094b9..a0e0dad1b419 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
31 | 31 | ||
32 | #include <linux/mmc/card.h> | 32 | #include <linux/mmc/card.h> |
33 | #include <linux/mmc/host.h> | ||
33 | #include <linux/mmc/protocol.h> | 34 | #include <linux/mmc/protocol.h> |
34 | 35 | ||
35 | #include <asm/system.h> | 36 | #include <asm/system.h> |
@@ -171,8 +172,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
171 | 172 | ||
172 | brq.cmd.arg = req->sector << 9; | 173 | brq.cmd.arg = req->sector << 9; |
173 | brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | 174 | brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; |
174 | brq.data.timeout_ns = card->csd.tacc_ns * 10; | ||
175 | brq.data.timeout_clks = card->csd.tacc_clks * 10; | ||
176 | brq.data.blksz_bits = md->block_bits; | 175 | brq.data.blksz_bits = md->block_bits; |
177 | brq.data.blksz = 1 << md->block_bits; | 176 | brq.data.blksz = 1 << md->block_bits; |
178 | brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); | 177 | brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); |
@@ -180,6 +179,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
180 | brq.stop.arg = 0; | 179 | brq.stop.arg = 0; |
181 | brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC; | 180 | brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC; |
182 | 181 | ||
182 | mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ); | ||
183 | |||
183 | if (rq_data_dir(req) == READ) { | 184 | if (rq_data_dir(req) == READ) { |
184 | brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK; | 185 | brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK; |
185 | brq.data.flags |= MMC_DATA_READ; | 186 | brq.data.flags |= MMC_DATA_READ; |
@@ -187,12 +188,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
187 | brq.cmd.opcode = MMC_WRITE_BLOCK; | 188 | brq.cmd.opcode = MMC_WRITE_BLOCK; |
188 | brq.data.flags |= MMC_DATA_WRITE; | 189 | brq.data.flags |= MMC_DATA_WRITE; |
189 | brq.data.blocks = 1; | 190 | brq.data.blocks = 1; |
190 | |||
191 | /* | ||
192 | * Scale up the timeout by the r2w factor | ||
193 | */ | ||
194 | brq.data.timeout_ns <<= card->csd.r2w_factor; | ||
195 | brq.data.timeout_clks <<= card->csd.r2w_factor; | ||
196 | } | 191 | } |
197 | 192 | ||
198 | if (brq.data.blocks > 1) { | 193 | if (brq.data.blocks > 1) { |
@@ -324,52 +319,11 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
324 | md->read_only = mmc_blk_readonly(card); | 319 | md->read_only = mmc_blk_readonly(card); |
325 | 320 | ||
326 | /* | 321 | /* |
327 | * Figure out a workable block size. MMC cards have: | 322 | * Both SD and MMC specifications state (although a bit |
328 | * - two block sizes, one for read and one for write. | 323 | * unclearly in the MMC case) that a block size of 512 |
329 | * - may support partial reads and/or writes | 324 | * bytes must always be supported by the card. |
330 | * (allows block sizes smaller than specified) | ||
331 | */ | ||
332 | md->block_bits = card->csd.read_blkbits; | ||
333 | if (card->csd.write_blkbits != card->csd.read_blkbits) { | ||
334 | if (card->csd.write_blkbits < card->csd.read_blkbits && | ||
335 | card->csd.read_partial) { | ||
336 | /* | ||
337 | * write block size is smaller than read block | ||
338 | * size, but we support partial reads, so choose | ||
339 | * the smaller write block size. | ||
340 | */ | ||
341 | md->block_bits = card->csd.write_blkbits; | ||
342 | } else if (card->csd.write_blkbits > card->csd.read_blkbits && | ||
343 | card->csd.write_partial) { | ||
344 | /* | ||
345 | * read block size is smaller than write block | ||
346 | * size, but we support partial writes. Use read | ||
347 | * block size. | ||
348 | */ | ||
349 | } else { | ||
350 | /* | ||
351 | * We don't support this configuration for writes. | ||
352 | */ | ||
353 | printk(KERN_ERR "%s: unable to select block size for " | ||
354 | "writing (rb%u wb%u rp%u wp%u)\n", | ||
355 | mmc_card_id(card), | ||
356 | 1 << card->csd.read_blkbits, | ||
357 | 1 << card->csd.write_blkbits, | ||
358 | card->csd.read_partial, | ||
359 | card->csd.write_partial); | ||
360 | md->read_only = 1; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * Refuse to allow block sizes smaller than 512 bytes. | ||
366 | */ | 325 | */ |
367 | if (md->block_bits < 9) { | 326 | md->block_bits = 9; |
368 | printk(KERN_ERR "%s: unable to support block size %u\n", | ||
369 | mmc_card_id(card), 1 << md->block_bits); | ||
370 | ret = -EINVAL; | ||
371 | goto err_kfree; | ||
372 | } | ||
373 | 327 | ||
374 | md->disk = alloc_disk(1 << MMC_SHIFT); | 328 | md->disk = alloc_disk(1 << MMC_SHIFT); |
375 | if (md->disk == NULL) { | 329 | if (md->disk == NULL) { |
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index c1f021eddffa..ba095aebedff 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -77,7 +77,7 @@ struct mmc_host { | |||
77 | struct device *dev; | 77 | struct device *dev; |
78 | struct class_device class_dev; | 78 | struct class_device class_dev; |
79 | int index; | 79 | int index; |
80 | struct mmc_host_ops *ops; | 80 | const struct mmc_host_ops *ops; |
81 | unsigned int f_min; | 81 | unsigned int f_min; |
82 | unsigned int f_max; | 82 | unsigned int f_max; |
83 | u32 ocr_avail; | 83 | u32 ocr_avail; |
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 03a14a30c46a..627e2c08ce41 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h | |||
@@ -105,6 +105,8 @@ extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int); | |||
105 | extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int, | 105 | extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int, |
106 | struct mmc_command *, int); | 106 | struct mmc_command *, int); |
107 | 107 | ||
108 | extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *, int); | ||
109 | |||
108 | extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card); | 110 | extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card); |
109 | 111 | ||
110 | static inline void mmc_claim_host(struct mmc_host *host) | 112 | static inline void mmc_claim_host(struct mmc_host *host) |