Commit a00fc090 authored by Pierre Ossman's avatar Pierre Ossman Committed by Linus Torvalds

[PATCH] sd: read-only switch

Support for the read-only switch on SD cards which must be enforced by the
host.
Signed-off-by: default avatarPierre Ossman <drzeus@drzeus.cx>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 335eadf2
...@@ -413,8 +413,7 @@ static void mmc_decode_cid(struct mmc_card *card) ...@@ -413,8 +413,7 @@ static void mmc_decode_cid(struct mmc_card *card)
card->cid.month = UNSTUFF_BITS(resp, 8, 4); card->cid.month = UNSTUFF_BITS(resp, 8, 4);
card->cid.year += 2000; /* SD cards year offset */ card->cid.year += 2000; /* SD cards year offset */
} } else {
else {
/* /*
* The selection of the format here is based upon published * The selection of the format here is based upon published
* specs from sandisk and from what people have reported. * specs from sandisk and from what people have reported.
...@@ -494,8 +493,7 @@ static void mmc_decode_csd(struct mmc_card *card) ...@@ -494,8 +493,7 @@ static void mmc_decode_csd(struct mmc_card *card)
csd->capacity = (1 + m) << (e + 2); csd->capacity = (1 + m) << (e + 2);
csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
} } else {
else {
/* /*
* We only understand CSD structure v1.1 and v1.2. * We only understand CSD structure v1.1 and v1.2.
* v1.2 has extra information in bits 15, 11 and 10. * 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,10 +736,20 @@ static void mmc_discover_cards(struct mmc_host *host)
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err != MMC_ERR_NONE) if (err != MMC_ERR_NONE)
mmc_card_set_dead(card); mmc_card_set_dead(card);
else else {
card->rca = cmd.resp[0] >> 16; card->rca = cmd.resp[0] >> 16;
}
else { if (!host->ops->get_ro) {
printk(KERN_WARNING "%s: host does not "
"support reading read-only "
"switch. assuming write-enable.\n",
mmc_hostname(host));
} else {
if (host->ops->get_ro(host))
mmc_card_set_readonly(card);
}
}
} else {
cmd.opcode = MMC_SET_RELATIVE_ADDR; cmd.opcode = MMC_SET_RELATIVE_ADDR;
cmd.arg = card->rca << 16; cmd.arg = card->rca << 16;
cmd.flags = MMC_RSP_R1; cmd.flags = MMC_RSP_R1;
...@@ -833,24 +841,23 @@ static void mmc_setup(struct mmc_host *host) ...@@ -833,24 +841,23 @@ static void mmc_setup(struct mmc_host *host)
int err; int err;
u32 ocr; u32 ocr;
host->mode = MMC_MODE_MMC; host->mode = MMC_MODE_SD;
mmc_power_up(host); mmc_power_up(host);
mmc_idle_cards(host); mmc_idle_cards(host);
err = mmc_send_op_cond(host, 0, &ocr); err = mmc_send_app_op_cond(host, 0, &ocr);
/* /*
* If we fail to detect any cards then try * If we fail to detect any SD cards then try
* searching for SD cards. * searching for MMC cards.
*/ */
if (err != MMC_ERR_NONE) if (err != MMC_ERR_NONE) {
{ host->mode = MMC_MODE_MMC;
err = mmc_send_app_op_cond(host, 0, &ocr);
err = mmc_send_op_cond(host, 0, &ocr);
if (err != MMC_ERR_NONE) if (err != MMC_ERR_NONE)
return; return;
host->mode = MMC_MODE_SD;
} }
host->ocr = mmc_select_voltage(host, ocr); host->ocr = mmc_select_voltage(host, ocr);
......
...@@ -95,6 +95,10 @@ static int mmc_blk_open(struct inode *inode, struct file *filp) ...@@ -95,6 +95,10 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
if (md->usage == 2) if (md->usage == 2)
check_disk_change(inode->i_bdev); check_disk_change(inode->i_bdev);
ret = 0; ret = 0;
if ((filp->f_mode & FMODE_WRITE) &&
mmc_card_readonly(md->queue.card))
ret = -EROFS;
} }
return ret; return ret;
...@@ -403,9 +407,10 @@ static int mmc_blk_probe(struct mmc_card *card) ...@@ -403,9 +407,10 @@ static int mmc_blk_probe(struct mmc_card *card)
if (err) if (err)
goto out; goto out;
printk(KERN_INFO "%s: %s %s %dKiB\n", printk(KERN_INFO "%s: %s %s %dKiB %s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
(card->csd.capacity << card->csd.read_blkbits) / 1024); (card->csd.capacity << card->csd.read_blkbits) / 1024,
mmc_card_readonly(card)?"(ro)":"");
mmc_set_drvdata(card, md); mmc_set_drvdata(card, md);
add_disk(md->disk); add_disk(md->disk);
......
...@@ -48,6 +48,7 @@ struct mmc_card { ...@@ -48,6 +48,7 @@ struct mmc_card {
#define MMC_STATE_DEAD (1<<1) /* device no longer in stack */ #define MMC_STATE_DEAD (1<<1) /* device no longer in stack */
#define MMC_STATE_BAD (1<<2) /* unrecognised device */ #define MMC_STATE_BAD (1<<2) /* unrecognised device */
#define MMC_STATE_SDCARD (1<<3) /* is an SD card */ #define MMC_STATE_SDCARD (1<<3) /* is an SD card */
#define MMC_STATE_READONLY (1<<4) /* card is read-only */
u32 raw_cid[4]; /* raw card CID */ u32 raw_cid[4]; /* raw card CID */
u32 raw_csd[4]; /* raw card CSD */ u32 raw_csd[4]; /* raw card CSD */
struct mmc_cid cid; /* card identification */ struct mmc_cid cid; /* card identification */
...@@ -58,11 +59,13 @@ struct mmc_card { ...@@ -58,11 +59,13 @@ struct mmc_card {
#define mmc_card_dead(c) ((c)->state & MMC_STATE_DEAD) #define mmc_card_dead(c) ((c)->state & MMC_STATE_DEAD)
#define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD) #define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD)
#define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD) #define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD)
#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
#define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD) #define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD)
#define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD) #define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD)
#define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD) #define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD)
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
#define mmc_card_name(c) ((c)->cid.prod_name) #define mmc_card_name(c) ((c)->cid.prod_name)
#define mmc_card_id(c) ((c)->dev.bus_id) #define mmc_card_id(c) ((c)->dev.bus_id)
......
...@@ -62,6 +62,7 @@ struct mmc_ios { ...@@ -62,6 +62,7 @@ struct mmc_ios {
struct mmc_host_ops { struct mmc_host_ops {
void (*request)(struct mmc_host *host, struct mmc_request *req); void (*request)(struct mmc_host *host, struct mmc_request *req);
void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios); void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
int (*get_ro)(struct mmc_host *host);
}; };
struct mmc_card; struct mmc_card;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment