aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <drzeus-list@drzeus.cx>2005-09-06 18:18:52 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 19:57:50 -0400
commita00fc09029f02ca833cf90e5d5625f08c4ac4f51 (patch)
tree02774c6f35623a27fbefbe1fe7f26f4a0f5fdd32
parent335eadf2ef6a1122a720aea98e758e5d431da87d (diff)
[PATCH] sd: read-only switch
Support for the read-only switch on SD cards which must be enforced by the host. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx> Cc: Russell King <rmk@arm.linux.org.uk> Cc: David Brownell <david-b@pacbell.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/mmc/mmc.c39
-rw-r--r--drivers/mmc/mmc_block.c9
-rw-r--r--include/linux/mmc/card.h3
-rw-r--r--include/linux/mmc/host.h1
4 files changed, 34 insertions, 18 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 294961a102ca..725c6ad3eb64 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -413,8 +413,7 @@ static void mmc_decode_cid(struct mmc_card *card)
413 card->cid.month = UNSTUFF_BITS(resp, 8, 4); 413 card->cid.month = UNSTUFF_BITS(resp, 8, 4);
414 414
415 card->cid.year += 2000; /* SD cards year offset */ 415 card->cid.year += 2000; /* SD cards year offset */
416 } 416 } else {
417 else {
418 /* 417 /*
419 * The selection of the format here is based upon published 418 * The selection of the format here is based upon published
420 * specs from sandisk and from what people have reported. 419 * specs from sandisk and from what people have reported.
@@ -494,8 +493,7 @@ static void mmc_decode_csd(struct mmc_card *card)
494 csd->capacity = (1 + m) << (e + 2); 493 csd->capacity = (1 + m) << (e + 2);
495 494
496 csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); 495 csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
497 } 496 } else {
498 else {
499 /* 497 /*
500 * We only understand CSD structure v1.1 and v1.2. 498 * We only understand CSD structure v1.1 and v1.2.
501 * v1.2 has extra information in bits 15, 11 and 10. 499 * v1.2 has extra information in bits 15, 11 and 10.
@@ -738,10 +736,20 @@ static void mmc_discover_cards(struct mmc_host *host)
738 err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); 736 err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
739 if (err != MMC_ERR_NONE) 737 if (err != MMC_ERR_NONE)
740 mmc_card_set_dead(card); 738 mmc_card_set_dead(card);
741 else 739 else {
742 card->rca = cmd.resp[0] >> 16; 740 card->rca = cmd.resp[0] >> 16;
743 } 741
744 else { 742 if (!host->ops->get_ro) {
743 printk(KERN_WARNING "%s: host does not "
744 "support reading read-only "
745 "switch. assuming write-enable.\n",
746 mmc_hostname(host));
747 } else {
748 if (host->ops->get_ro(host))
749 mmc_card_set_readonly(card);
750 }
751 }
752 } else {
745 cmd.opcode = MMC_SET_RELATIVE_ADDR; 753 cmd.opcode = MMC_SET_RELATIVE_ADDR;
746 cmd.arg = card->rca << 16; 754 cmd.arg = card->rca << 16;
747 cmd.flags = MMC_RSP_R1; 755 cmd.flags = MMC_RSP_R1;
@@ -833,24 +841,23 @@ static void mmc_setup(struct mmc_host *host)
833 int err; 841 int err;
834 u32 ocr; 842 u32 ocr;
835 843
836 host->mode = MMC_MODE_MMC; 844 host->mode = MMC_MODE_SD;
837 845
838 mmc_power_up(host); 846 mmc_power_up(host);
839 mmc_idle_cards(host); 847 mmc_idle_cards(host);
840 848
841 err = mmc_send_op_cond(host, 0, &ocr); 849 err = mmc_send_app_op_cond(host, 0, &ocr);
842 850
843 /* 851 /*
844 * If we fail to detect any cards then try 852 * If we fail to detect any SD cards then try
845 * searching for SD cards. 853 * searching for MMC cards.
846 */ 854 */
847 if (err != MMC_ERR_NONE) 855 if (err != MMC_ERR_NONE) {
848 { 856 host->mode = MMC_MODE_MMC;
849 err = mmc_send_app_op_cond(host, 0, &ocr); 857
858 err = mmc_send_op_cond(host, 0, &ocr);
850 if (err != MMC_ERR_NONE) 859 if (err != MMC_ERR_NONE)
851 return; 860 return;
852
853 host->mode = MMC_MODE_SD;
854 } 861 }
855 862
856 host->ocr = mmc_select_voltage(host, ocr); 863 host->ocr = mmc_select_voltage(host, ocr);
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index d4eee99c2bf6..fa83f15fdf16 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -95,6 +95,10 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
95 if (md->usage == 2) 95 if (md->usage == 2)
96 check_disk_change(inode->i_bdev); 96 check_disk_change(inode->i_bdev);
97 ret = 0; 97 ret = 0;
98
99 if ((filp->f_mode & FMODE_WRITE) &&
100 mmc_card_readonly(md->queue.card))
101 ret = -EROFS;
98 } 102 }
99 103
100 return ret; 104 return ret;
@@ -403,9 +407,10 @@ static int mmc_blk_probe(struct mmc_card *card)
403 if (err) 407 if (err)
404 goto out; 408 goto out;
405 409
406 printk(KERN_INFO "%s: %s %s %dKiB\n", 410 printk(KERN_INFO "%s: %s %s %dKiB %s\n",
407 md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), 411 md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
408 (card->csd.capacity << card->csd.read_blkbits) / 1024); 412 (card->csd.capacity << card->csd.read_blkbits) / 1024,
413 mmc_card_readonly(card)?"(ro)":"");
409 414
410 mmc_set_drvdata(card, md); 415 mmc_set_drvdata(card, md);
411 add_disk(md->disk); 416 add_disk(md->disk);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 538e8c86336c..0e9ec01b9c5b 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -48,6 +48,7 @@ struct mmc_card {
48#define MMC_STATE_DEAD (1<<1) /* device no longer in stack */ 48#define MMC_STATE_DEAD (1<<1) /* device no longer in stack */
49#define MMC_STATE_BAD (1<<2) /* unrecognised device */ 49#define MMC_STATE_BAD (1<<2) /* unrecognised device */
50#define MMC_STATE_SDCARD (1<<3) /* is an SD card */ 50#define MMC_STATE_SDCARD (1<<3) /* is an SD card */
51#define MMC_STATE_READONLY (1<<4) /* card is read-only */
51 u32 raw_cid[4]; /* raw card CID */ 52 u32 raw_cid[4]; /* raw card CID */
52 u32 raw_csd[4]; /* raw card CSD */ 53 u32 raw_csd[4]; /* raw card CSD */
53 struct mmc_cid cid; /* card identification */ 54 struct mmc_cid cid; /* card identification */
@@ -58,11 +59,13 @@ struct mmc_card {
58#define mmc_card_dead(c) ((c)->state & MMC_STATE_DEAD) 59#define mmc_card_dead(c) ((c)->state & MMC_STATE_DEAD)
59#define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD) 60#define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD)
60#define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD) 61#define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD)
62#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
61 63
62#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) 64#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
63#define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD) 65#define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD)
64#define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD) 66#define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD)
65#define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD) 67#define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD)
68#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
66 69
67#define mmc_card_name(c) ((c)->cid.prod_name) 70#define mmc_card_name(c) ((c)->cid.prod_name)
68#define mmc_card_id(c) ((c)->dev.bus_id) 71#define mmc_card_id(c) ((c)->dev.bus_id)
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 845020d90c60..8c5f71376e41 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -62,6 +62,7 @@ struct mmc_ios {
62struct mmc_host_ops { 62struct mmc_host_ops {
63 void (*request)(struct mmc_host *host, struct mmc_request *req); 63 void (*request)(struct mmc_host *host, struct mmc_request *req);
64 void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios); 64 void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
65 int (*get_ro)(struct mmc_host *host);
65}; 66};
66 67
67struct mmc_card; 68struct mmc_card;