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

Commit 4e078fbd authored by Russell King's avatar Russell King
Browse files

mmc: omap: remove private DMA API implementation



Remove the private DMA API implementation from omap, making it use
entirely the DMA engine API.

Tested-by: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 3451c067
Loading
Loading
Loading
Loading
+6 −229
Original line number Diff line number Diff line
@@ -101,8 +101,6 @@

struct mmc_omap_host;

#define USE_DMA_PRIVATE

struct mmc_omap_slot {
	int			id;
	unsigned int		vdd;
@@ -162,12 +160,6 @@ struct mmc_omap_host {
	unsigned		use_dma:1;
	unsigned		brs_received:1, dma_done:1;
	unsigned		dma_in_use:1;
#ifdef USE_DMA_PRIVATE
	unsigned		dma_is_read:1;
	int			dma_ch;
	struct timer_list	dma_timer;
	unsigned		dma_len;
#endif
	spinlock_t		dma_lock;

	struct mmc_omap_slot    *slots[OMAP_MMC_MAX_SLOTS];
@@ -419,13 +411,6 @@ mmc_omap_release_dma(struct mmc_omap_host *host, struct mmc_data *data,
	struct device *dev = mmc_dev(host->mmc);
	struct dma_chan *c;

#ifdef USE_DMA_PRIVATE
	BUG_ON(host->dma_ch < 0);
	if (data->error)
		omap_stop_dma(host->dma_ch);
	/* Release DMA channel lazily */
	mod_timer(&host->dma_timer, jiffies + HZ);
#endif
	if (data->flags & MMC_DATA_WRITE) {
		dma_data_dir = DMA_TO_DEVICE;
		c = host->dma_tx;
@@ -548,18 +533,6 @@ mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data)
		mmc_omap_xfer_done(host, data);
}

#ifdef USE_DMA_PRIVATE
static void
mmc_omap_dma_timer(unsigned long data)
{
	struct mmc_omap_host *host = (struct mmc_omap_host *) data;

	BUG_ON(host->dma_ch < 0);
	omap_free_dma(host->dma_ch);
	host->dma_ch = -1;
}
#endif

static void
mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data)
{
@@ -928,163 +901,6 @@ static void mmc_omap_dma_callback(void *priv)
	mmc_omap_dma_done(host, data);
}

#ifdef USE_DMA_PRIVATE
/* Prepare to transfer the next segment of a scatterlist */
static void
mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
{
	int dma_ch = host->dma_ch;
	unsigned long data_addr;
	u16 buf, frame;
	u32 count;
	struct scatterlist *sg = &data->sg[host->sg_idx];
	int src_port = 0;
	int dst_port = 0;
	int sync_dev = 0;

	data_addr = host->phys_base + OMAP_MMC_REG(host, DATA);
	frame = data->blksz;
	count = sg_dma_len(sg);

	if ((data->blocks == 1) && (count > data->blksz))
		count = frame;

	host->dma_len = count;

	/* FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx and 24xx.
	 * Use 16 or 32 word frames when the blocksize is at least that large.
	 * Blocksize is usually 512 bytes; but not for some SD reads.
	 */
	if (cpu_is_omap15xx() && frame > 32)
		frame = 32;
	else if (frame > 64)
		frame = 64;
	count /= frame;
	frame >>= 1;

	if (!(data->flags & MMC_DATA_WRITE)) {
		buf = 0x800f | ((frame - 1) << 8);

		if (cpu_class_is_omap1()) {
			src_port = OMAP_DMA_PORT_TIPB;
			dst_port = OMAP_DMA_PORT_EMIFF;
		}
		if (cpu_is_omap24xx())
			sync_dev = OMAP24XX_DMA_MMC1_RX;

		omap_set_dma_src_params(dma_ch, src_port,
					OMAP_DMA_AMODE_CONSTANT,
					data_addr, 0, 0);
		omap_set_dma_dest_params(dma_ch, dst_port,
					 OMAP_DMA_AMODE_POST_INC,
					 sg_dma_address(sg), 0, 0);
		omap_set_dma_dest_data_pack(dma_ch, 1);
		omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
	} else {
		buf = 0x0f80 | ((frame - 1) << 0);

		if (cpu_class_is_omap1()) {
			src_port = OMAP_DMA_PORT_EMIFF;
			dst_port = OMAP_DMA_PORT_TIPB;
		}
		if (cpu_is_omap24xx())
			sync_dev = OMAP24XX_DMA_MMC1_TX;

		omap_set_dma_dest_params(dma_ch, dst_port,
					 OMAP_DMA_AMODE_CONSTANT,
					 data_addr, 0, 0);
		omap_set_dma_src_params(dma_ch, src_port,
					OMAP_DMA_AMODE_POST_INC,
					sg_dma_address(sg), 0, 0);
		omap_set_dma_src_data_pack(dma_ch, 1);
		omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
	}

	/* Max limit for DMA frame count is 0xffff */
	BUG_ON(count > 0xffff);

	OMAP_MMC_WRITE(host, BUF, buf);
	omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16,
				     frame, count, OMAP_DMA_SYNC_FRAME,
				     sync_dev, 0);
}

/* A scatterlist segment completed */
static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
{
	struct mmc_omap_host *host = (struct mmc_omap_host *) data;
	struct mmc_data *mmcdat = host->data;

	if (unlikely(host->dma_ch < 0)) {
		dev_err(mmc_dev(host->mmc),
			"DMA callback while DMA not enabled\n");
		return;
	}
	/* FIXME: We really should do something to _handle_ the errors */
	if (ch_status & OMAP1_DMA_TOUT_IRQ) {
		dev_err(mmc_dev(host->mmc),"DMA timeout\n");
		return;
	}
	if (ch_status & OMAP_DMA_DROP_IRQ) {
		dev_err(mmc_dev(host->mmc), "DMA sync error\n");
		return;
	}
	if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) {
		return;
	}
	mmcdat->bytes_xfered += host->dma_len;
	host->sg_idx++;
	if (host->sg_idx < host->sg_len) {
		mmc_omap_prepare_dma(host, host->data);
		omap_start_dma(host->dma_ch);
	} else
		mmc_omap_dma_done(host, host->data);
}

static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data *data)
{
	const char *dma_dev_name;
	int sync_dev, dma_ch, is_read, r;

	is_read = !(data->flags & MMC_DATA_WRITE);
	del_timer_sync(&host->dma_timer);
	if (host->dma_ch >= 0) {
		if (is_read == host->dma_is_read)
			return 0;
		omap_free_dma(host->dma_ch);
		host->dma_ch = -1;
	}

	if (is_read) {
		if (host->id == 0) {
			sync_dev = OMAP_DMA_MMC_RX;
			dma_dev_name = "MMC1 read";
		} else {
			sync_dev = OMAP_DMA_MMC2_RX;
			dma_dev_name = "MMC2 read";
		}
	} else {
		if (host->id == 0) {
			sync_dev = OMAP_DMA_MMC_TX;
			dma_dev_name = "MMC1 write";
		} else {
			sync_dev = OMAP_DMA_MMC2_TX;
			dma_dev_name = "MMC2 write";
		}
	}
	r = omap_request_dma(sync_dev, dma_dev_name, mmc_omap_dma_cb,
			     host, &dma_ch);
	if (r != 0) {
		dev_dbg(mmc_dev(host->mmc), "omap_request_dma() failed with %d\n", r);
		return r;
	}
	host->dma_ch = dma_ch;
	host->dma_is_read = is_read;

	return 0;
}
#endif

static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req)
{
	u16 reg;
@@ -1229,39 +1045,14 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
		return;
	}
 use_pio:
#ifdef USE_DMA_PRIVATE
	if (use_dma) {
		if (mmc_omap_get_dma_channel(host, data) == 0) {
			enum dma_data_direction dma_data_dir;

			if (data->flags & MMC_DATA_WRITE)
				dma_data_dir = DMA_TO_DEVICE;
			else
				dma_data_dir = DMA_FROM_DEVICE;

			host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
						sg_len, dma_data_dir);
			host->total_bytes_left = 0;
			mmc_omap_prepare_dma(host, req->data);
			host->brs_received = 0;
			host->dma_done = 0;
			host->dma_in_use = 1;
		} else
			use_dma = 0;
	}
#else
	use_dma = 0;
#endif

	/* Revert to PIO? */
	if (!use_dma) {
	OMAP_MMC_WRITE(host, BUF, 0x1f1f);
	host->total_bytes_left = data->blocks * block_size;
	host->sg_len = sg_len;
	mmc_omap_sg_to_buf(host);
	host->dma_in_use = 0;
}
}

static void mmc_omap_start_request(struct mmc_omap_host *host,
				   struct mmc_request *req)
@@ -1277,12 +1068,7 @@ static void mmc_omap_start_request(struct mmc_omap_host *host,
		struct dma_chan *c = host->data->flags & MMC_DATA_WRITE ?
				host->dma_tx : host->dma_rx;

		if (c)
		dma_async_issue_pending(c);
#ifdef USE_DMA_PRIVATE
		else
			omap_start_dma(host->dma_ch);
#endif
	}
}

@@ -1566,9 +1352,6 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
	setup_timer(&host->clk_timer, mmc_omap_clk_timer, (unsigned long) host);

	spin_lock_init(&host->dma_lock);
#ifdef USE_DMA_PRIVATE
	setup_timer(&host->dma_timer, mmc_omap_dma_timer, (unsigned long) host);
#endif
	spin_lock_init(&host->slot_lock);
	init_waitqueue_head(&host->slot_wq);

@@ -1579,13 +1362,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
	host->id = pdev->id;
	host->mem_res = res;
	host->irq = irq;

	host->use_dma = 1;
#ifdef USE_DMA_PRIVATE
	host->dev->dma_mask = &pdata->dma_mask;
	host->dma_ch = -1;
#endif

	host->irq = irq;
	host->phys_base = host->mem_res->start;
	host->virt_base = ioremap(res->start, resource_size(res));