Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+23 −16
Original line number Diff line number Diff line
@@ -413,8 +413,7 @@ static void mmc_decode_cid(struct mmc_card *card)
		card->cid.month			= UNSTUFF_BITS(resp, 8, 4);

		card->cid.year += 2000; /* SD cards year offset */
	}
	else {
	} else {
		/*
		 * The selection of the format here is based upon published
		 * specs from sandisk and from what people have reported.
@@ -494,8 +493,7 @@ static void mmc_decode_csd(struct mmc_card *card)
		csd->capacity	  = (1 + m) << (e + 2);

		csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
	}
	else {
	} else {
		/*
		 * We only understand CSD structure v1.1 and v1.2.
		 * v1.2 has extra information in bits 15, 11 and 10.
@@ -738,10 +736,20 @@ static void mmc_discover_cards(struct mmc_host *host)
			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
			if (err != MMC_ERR_NONE)
				mmc_card_set_dead(card);
			else
			else {
				card->rca = cmd.resp[0] >> 16;

				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 {
			}
		} else {
			cmd.opcode = MMC_SET_RELATIVE_ADDR;
			cmd.arg = card->rca << 16;
			cmd.flags = MMC_RSP_R1;
@@ -833,24 +841,23 @@ static void mmc_setup(struct mmc_host *host)
		int err;
		u32 ocr;

		host->mode = MMC_MODE_MMC;
		host->mode = MMC_MODE_SD;

		mmc_power_up(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
		 * searching for SD cards.
		 * If we fail to detect any SD cards then try
		 * searching for MMC cards.
		 */
		if (err != MMC_ERR_NONE)
		{
			err = mmc_send_app_op_cond(host, 0, &ocr);
		if (err != MMC_ERR_NONE) {
			host->mode = MMC_MODE_MMC;

			err = mmc_send_op_cond(host, 0, &ocr);
			if (err != MMC_ERR_NONE)
				return;

			host->mode = MMC_MODE_SD;
		}

		host->ocr = mmc_select_voltage(host, ocr);
+7 −2
Original line number Diff line number Diff line
@@ -95,6 +95,10 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
		if (md->usage == 2)
			check_disk_change(inode->i_bdev);
		ret = 0;

		if ((filp->f_mode & FMODE_WRITE) &&
			mmc_card_readonly(md->queue.card))
			ret = -EROFS;
	}

	return ret;
@@ -403,9 +407,10 @@ static int mmc_blk_probe(struct mmc_card *card)
	if (err)
		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),
		(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);
	add_disk(md->disk);
+3 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ struct mmc_card {
#define MMC_STATE_DEAD		(1<<1)		/* device no longer in stack */
#define MMC_STATE_BAD		(1<<2)		/* unrecognised device */
#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_csd[4];	/* raw card CSD */
	struct mmc_cid		cid;		/* card identification */
@@ -58,11 +59,13 @@ struct mmc_card {
#define mmc_card_dead(c)	((c)->state & MMC_STATE_DEAD)
#define mmc_card_bad(c)		((c)->state & MMC_STATE_BAD)
#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_dead(c)	((c)->state |= MMC_STATE_DEAD)
#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_readonly(c) ((c)->state |= MMC_STATE_READONLY)

#define mmc_card_name(c)	((c)->cid.prod_name)
#define mmc_card_id(c)		((c)->dev.bus_id)
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ struct mmc_ios {
struct mmc_host_ops {
	void	(*request)(struct mmc_host *host, struct mmc_request *req);
	void	(*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
	int	(*get_ro)(struct mmc_host *host);
};

struct mmc_card;