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

Commit dfc13e84 authored by Hanumath Prasad's avatar Hanumath Prasad Committed by Chris Ball
Browse files

mmc: MMC 4.4 DDR support



Add support for Dual Data Rate MMC cards as defined in the 4.4
specification.

Signed-off-by: default avatarHanumath Prasad <hanumath.prasad@stericsson.com>
Cc: linux-mmc@vger.kernel.org
Acked-by: default avatarLinus Walleij <linus.walleij@stericsson.com>
Tested-by Zhangfei Gao <zhangfei.gao@marvell.com>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 99fc5131
Loading
Loading
Loading
Loading
+7 −3
Original line number Original line Diff line number Diff line
@@ -373,7 +373,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
			readcmd = MMC_READ_SINGLE_BLOCK;
			readcmd = MMC_READ_SINGLE_BLOCK;
			writecmd = MMC_WRITE_BLOCK;
			writecmd = MMC_WRITE_BLOCK;
		}
		}

		if (mmc_card_ddr_mode(card))
			brq.data.flags |= MMC_DDR_MODE;
		if (rq_data_dir(req) == READ) {
		if (rq_data_dir(req) == READ) {
			brq.cmd.opcode = readcmd;
			brq.cmd.opcode = readcmd;
			brq.data.flags |= MMC_DATA_READ;
			brq.data.flags |= MMC_DATA_READ;
@@ -655,8 +656,11 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
	struct mmc_command cmd;
	struct mmc_command cmd;
	int err;
	int err;


	/* Block-addressed cards ignore MMC_SET_BLOCKLEN. */
	/*
	if (mmc_card_blockaddr(card))
	 * Block-addressed and ddr mode supported cards
	 * ignore MMC_SET_BLOCKLEN.
	 */
	if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
		return 0;
		return 0;


	mmc_claim_host(card->host);
	mmc_claim_host(card->host);
+35 −2
Original line number Original line Diff line number Diff line
@@ -258,6 +258,21 @@ static int mmc_read_ext_csd(struct mmc_card *card)
	}
	}


	switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) {
	switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) {
	case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 |
	     EXT_CSD_CARD_TYPE_26:
		card->ext_csd.hs_max_dtr = 52000000;
		card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52;
		break;
	case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 |
	     EXT_CSD_CARD_TYPE_26:
		card->ext_csd.hs_max_dtr = 52000000;
		card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V;
		break;
	case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 |
	     EXT_CSD_CARD_TYPE_26:
		card->ext_csd.hs_max_dtr = 52000000;
		card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V;
		break;
	case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
	case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
		card->ext_csd.hs_max_dtr = 52000000;
		card->ext_csd.hs_max_dtr = 52000000;
		break;
		break;
@@ -502,6 +517,18 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,


	mmc_set_clock(host, max_dtr);
	mmc_set_clock(host, max_dtr);


	/*
	 * Activate DDR50 mode (if supported).
	 */
	if (mmc_card_highspeed(card)) {
		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
			&& (host->caps & (MMC_CAP_1_8V_DDR)))
				mmc_card_set_ddr_mode(card);
		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
			&& (host->caps & (MMC_CAP_1_2V_DDR)))
				mmc_card_set_ddr_mode(card);
	}

	/*
	/*
	 * Activate wide bus (if supported).
	 * Activate wide bus (if supported).
	 */
	 */
@@ -510,9 +537,15 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
		unsigned ext_csd_bit, bus_width;
		unsigned ext_csd_bit, bus_width;


		if (host->caps & MMC_CAP_8_BIT_DATA) {
		if (host->caps & MMC_CAP_8_BIT_DATA) {
			if (mmc_card_ddr_mode(card))
				ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8;
			else
				ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
				ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
			bus_width = MMC_BUS_WIDTH_8;
			bus_width = MMC_BUS_WIDTH_8;
		} else {
		} else {
			if (mmc_card_ddr_mode(card))
				ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4;
			else
				ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
				ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
			bus_width = MMC_BUS_WIDTH_4;
			bus_width = MMC_BUS_WIDTH_4;
		}
		}
+4 −0
Original line number Original line Diff line number Diff line
@@ -48,6 +48,7 @@ struct mmc_ext_csd {
	unsigned int		sa_timeout;		/* Units: 100ns */
	unsigned int		sa_timeout;		/* Units: 100ns */
	unsigned int		hs_max_dtr;
	unsigned int		hs_max_dtr;
	unsigned int		sectors;
	unsigned int		sectors;
	unsigned int		card_type;
	unsigned int		hc_erase_size;		/* In sectors */
	unsigned int		hc_erase_size;		/* In sectors */
	unsigned int		hc_erase_timeout;	/* In milliseconds */
	unsigned int		hc_erase_timeout;	/* In milliseconds */
	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
@@ -113,6 +114,7 @@ struct mmc_card {
#define MMC_STATE_READONLY	(1<<1)		/* card is read-only */
#define MMC_STATE_READONLY	(1<<1)		/* card is read-only */
#define MMC_STATE_HIGHSPEED	(1<<2)		/* card is in high speed mode */
#define MMC_STATE_HIGHSPEED	(1<<2)		/* card is in high speed mode */
#define MMC_STATE_BLOCKADDR	(1<<3)		/* card uses block-addressing */
#define MMC_STATE_BLOCKADDR	(1<<3)		/* card uses block-addressing */
#define MMC_STATE_HIGHSPEED_DDR (1<<4)		/* card is in high speed mode */
	unsigned int		quirks; 	/* card quirks */
	unsigned int		quirks; 	/* card quirks */
#define MMC_QUIRK_LENIENT_FN0	(1<<0)		/* allow SDIO FN0 writes outside of the VS CCCR range */
#define MMC_QUIRK_LENIENT_FN0	(1<<0)		/* allow SDIO FN0 writes outside of the VS CCCR range */
#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)	/* use func->cur_blksize */
#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)	/* use func->cur_blksize */
@@ -154,11 +156,13 @@ struct mmc_card {
#define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
#define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
#define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
#define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
#define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
#define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
#define mmc_card_ddr_mode(c)	((c)->state & MMC_STATE_HIGHSPEED_DDR)


#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_readonly(c) ((c)->state |= MMC_STATE_READONLY)
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)


static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
{
{
+1 −0
Original line number Original line Diff line number Diff line
@@ -109,6 +109,7 @@ struct mmc_data {
#define MMC_DATA_WRITE	(1 << 8)
#define MMC_DATA_WRITE	(1 << 8)
#define MMC_DATA_READ	(1 << 9)
#define MMC_DATA_READ	(1 << 9)
#define MMC_DATA_STREAM	(1 << 10)
#define MMC_DATA_STREAM	(1 << 10)
#define MMC_DDR_MODE	(1 << 11)


	unsigned int		bytes_xfered;
	unsigned int		bytes_xfered;


+4 −0
Original line number Original line Diff line number Diff line
@@ -158,6 +158,10 @@ struct mmc_host {
#define MMC_CAP_NONREMOVABLE	(1 << 8)	/* Nonremovable e.g. eMMC */
#define MMC_CAP_NONREMOVABLE	(1 << 8)	/* Nonremovable e.g. eMMC */
#define MMC_CAP_WAIT_WHILE_BUSY	(1 << 9)	/* Waits while card is busy */
#define MMC_CAP_WAIT_WHILE_BUSY	(1 << 9)	/* Waits while card is busy */
#define MMC_CAP_ERASE		(1 << 10)	/* Allow erase/trim commands */
#define MMC_CAP_ERASE		(1 << 10)	/* Allow erase/trim commands */
#define MMC_CAP_1_8V_DDR	(1 << 11)	/* can support */
						/* DDR mode at 1.8V */
#define MMC_CAP_1_2V_DDR	(1 << 12)	/* can support */
						/* DDR mode at 1.2V */


	mmc_pm_flag_t		pm_caps;	/* supported pm features */
	mmc_pm_flag_t		pm_caps;	/* supported pm features */


Loading