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

Commit 2c171bf1 authored by Pavel Pisa's avatar Pavel Pisa Committed by Russell King
Browse files

[ARM] 3531/1: i.MX/MX1 SD/MMC ensure, that clock are stopped before new command and cleanups



Patch from Pavel Pisa

There has been problems that for some paths that clock are not stopped
during new command programming and initiation. Result is issuing
of incorrect command to the card. Some other problems are cleaned too.
Noisy report of known ERRATUM #4 has been suppressed.

Signed-off-by: default avatarPavel Pisa <pisa@cmp.felk.cvut.cz>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent a54c9d30
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -310,7 +310,7 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
		}
		else
			data->bytes_xfered =
				(data->blocks * (1 << data->blksz_bits)) -
				(data->blocks * data->blksz) -
				host->pio.len;
	}

@@ -575,7 +575,7 @@ static int
au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
{

	int datalen = data->blocks * (1 << data->blksz_bits);
	int datalen = data->blocks * data->blksz;

	if (dma != 0)
		host->flags |= HOST_F_DMA;
@@ -596,7 +596,7 @@ au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
	if (host->dma.len == 0)
		return MMC_ERR_TIMEOUT;

	au_writel((1 << data->blksz_bits) - 1, HOST_BLKSIZE(host));
	au_writel(data->blksz - 1, HOST_BLKSIZE(host));

	if (host->flags & HOST_F_DMA) {
		int i;
+14 −10
Original line number Diff line number Diff line
@@ -218,6 +218,8 @@ static int imxmci_busy_wait_for_status(struct imxmci_host *host,
	if(!loops)
		return 0;

	/* The busy-wait is expected there for clock <8MHz due to SDHC hardware flaws */
	if(!(stat_mask & STATUS_END_CMD_RESP) || (host->mmc->ios.clock>=8000000))
		dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n",
			loops, where, *pstat, stat_mask);
	return loops;
@@ -333,6 +335,9 @@ static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd,
	WARN_ON(host->cmd != NULL);
	host->cmd = cmd;

	/* Ensure, that clock are stopped else command programming and start fails */
	imxmci_stop_clock(host);

	if (cmd->flags & MMC_RSP_BUSY)
		cmdat |= CMD_DAT_CONT_BUSY;

@@ -553,7 +558,7 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
	int trans_done = 0;
	unsigned int stat = *pstat;

	if(host->actual_bus_width == MMC_BUS_WIDTH_4)
	if(host->actual_bus_width != MMC_BUS_WIDTH_4)
		burst_len = 16;
	else
		burst_len = 64;
@@ -591,8 +596,7 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
			stat = MMC_STATUS;

			/* Flush extra bytes from FIFO */
			while(flush_len >= 2){
				flush_len -= 2;
			while(flush_len && !(stat & STATUS_DATA_TRANS_DONE)){
				i = MMC_BUFFER_ACCESS;
				stat = MMC_STATUS;
				stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */
@@ -746,10 +750,6 @@ static void imxmci_tasklet_fnc(unsigned long data)
			data_dir_mask = STATUS_DATA_TRANS_DONE;
		}

		imxmci_busy_wait_for_status(host, &stat,
				data_dir_mask,
				50, "imxmci_tasklet_fnc data");

		if(stat & data_dir_mask) {
			clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
			imxmci_data_done(host, stat);
@@ -865,7 +865,11 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)

		imxmci_stop_clock(host);
		MMC_CLK_RATE = (prescaler<<3) | clk;
		imxmci_start_clock(host);
		/*
		 * Under my understanding, clock should not be started there, because it would
		 * initiate SDHC sequencer and send last or random command into card
		 */
		/*imxmci_start_clock(host);*/

		dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE);
	} else {
+1 −0
Original line number Diff line number Diff line
@@ -951,6 +951,7 @@ static void mmc_read_scrs(struct mmc_host *host)
		data.timeout_ns = card->csd.tacc_ns * 10;
		data.timeout_clks = card->csd.tacc_clks * 10;
		data.blksz_bits = 3;
		data.blksz = 1 << 3;
		data.blocks = 1;
		data.flags = MMC_DATA_READ;
		data.sg = &sg;
+1 −0
Original line number Diff line number Diff line
@@ -175,6 +175,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
		brq.data.timeout_ns = card->csd.tacc_ns * 10;
		brq.data.timeout_clks = card->csd.tacc_clks * 10;
		brq.data.blksz_bits = md->block_bits;
		brq.data.blksz = 1 << md->block_bits;
		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
		brq.stop.opcode = MMC_STOP_TRANSMISSION;
		brq.stop.arg = 0;
+2 −2
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
		nob = 0xffff;

	writel(nob, host->base + MMC_NOB);
	writel(1 << data->blksz_bits, host->base + MMC_BLKLEN);
	writel(data->blksz, host->base + MMC_BLKLEN);

	clks = (unsigned long long)data->timeout_ns * CLOCKRATE;
	do_div(clks, 1000000000UL);
@@ -283,7 +283,7 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
	 * data blocks as being in error.
	 */
	if (data->error == MMC_ERR_NONE)
		data->bytes_xfered = data->blocks << data->blksz_bits;
		data->bytes_xfered = data->blocks * data->blksz;
	else
		data->bytes_xfered = 0;

Loading