Skip to content

Commit

Permalink
mmc: spi: Pull out common DMA parts from MXS MMC
Browse files Browse the repository at this point in the history
These parts will be used by the MXS SPI driver too.

Signed-off-by: Marek Vasut <marex@denx.de>
Acked-by: Chris Ball <cjb@laptop.org>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
  • Loading branch information
Marek Vasut authored and Mark Brown committed Aug 17, 2012
1 parent 646781d commit 65defb9
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 47 deletions.
88 changes: 42 additions & 46 deletions drivers/mmc/host/mxs-mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>
#include <linux/fsl/mxs-dma.h>
#include <linux/pinctrl/consumer.h>
#include <linux/stmp_device.h>
#include <linux/mmc/mxs-mmc.h>
Expand Down Expand Up @@ -69,13 +68,6 @@ struct mxs_mmc_host {
struct mmc_command *cmd;
struct mmc_data *data;

int dma_channel;
struct dma_chan *dmach;
struct mxs_dma_data dma_data;
unsigned int dma_dir;
enum dma_transfer_direction slave_dirn;
u32 ssp_pio_words[SSP_PIO_NUM];

unsigned char bus_width;
spinlock_t lock;
int sdio_irq_en;
Expand Down Expand Up @@ -163,7 +155,7 @@ static void mxs_mmc_request_done(struct mxs_mmc_host *host)

if (data) {
dma_unmap_sg(mmc_dev(host->mmc), data->sg,
data->sg_len, host->dma_dir);
data->sg_len, ssp->dma_dir);
/*
* If there was an error on any block, we mark all
* data blocks as being in error.
Expand Down Expand Up @@ -232,6 +224,7 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
struct mxs_mmc_host *host, unsigned long flags)
{
struct mxs_ssp *ssp = &host->ssp;
struct dma_async_tx_descriptor *desc;
struct mmc_data *data = host->data;
struct scatterlist * sgl;
Expand All @@ -240,31 +233,32 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
if (data) {
/* data */
dma_map_sg(mmc_dev(host->mmc), data->sg,
data->sg_len, host->dma_dir);
data->sg_len, ssp->dma_dir);
sgl = data->sg;
sg_len = data->sg_len;
} else {
/* pio */
sgl = (struct scatterlist *) host->ssp_pio_words;
sgl = (struct scatterlist *) ssp->ssp_pio_words;
sg_len = SSP_PIO_NUM;
}

desc = dmaengine_prep_slave_sg(host->dmach,
sgl, sg_len, host->slave_dirn, flags);
desc = dmaengine_prep_slave_sg(ssp->dmach,
sgl, sg_len, ssp->slave_dirn, flags);
if (desc) {
desc->callback = mxs_mmc_dma_irq_callback;
desc->callback_param = host;
} else {
if (data)
dma_unmap_sg(mmc_dev(host->mmc), data->sg,
data->sg_len, host->dma_dir);
data->sg_len, ssp->dma_dir);
}

return desc;
}

static void mxs_mmc_bc(struct mxs_mmc_host *host)
{
struct mxs_ssp *ssp = &host->ssp;
struct mmc_command *cmd = host->cmd;
struct dma_async_tx_descriptor *desc;
u32 ctrl0, cmd0, cmd1;
Expand All @@ -278,17 +272,17 @@ static void mxs_mmc_bc(struct mxs_mmc_host *host)
cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
}

host->ssp_pio_words[0] = ctrl0;
host->ssp_pio_words[1] = cmd0;
host->ssp_pio_words[2] = cmd1;
host->dma_dir = DMA_NONE;
host->slave_dirn = DMA_TRANS_NONE;
ssp->ssp_pio_words[0] = ctrl0;
ssp->ssp_pio_words[1] = cmd0;
ssp->ssp_pio_words[2] = cmd1;
ssp->dma_dir = DMA_NONE;
ssp->slave_dirn = DMA_TRANS_NONE;
desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK);
if (!desc)
goto out;

dmaengine_submit(desc);
dma_async_issue_pending(host->dmach);
dma_async_issue_pending(ssp->dmach);
return;

out:
Expand All @@ -298,6 +292,7 @@ static void mxs_mmc_bc(struct mxs_mmc_host *host)

static void mxs_mmc_ac(struct mxs_mmc_host *host)
{
struct mxs_ssp *ssp = &host->ssp;
struct mmc_command *cmd = host->cmd;
struct dma_async_tx_descriptor *desc;
u32 ignore_crc, get_resp, long_resp;
Expand All @@ -319,17 +314,17 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host)
cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
}

host->ssp_pio_words[0] = ctrl0;
host->ssp_pio_words[1] = cmd0;
host->ssp_pio_words[2] = cmd1;
host->dma_dir = DMA_NONE;
host->slave_dirn = DMA_TRANS_NONE;
ssp->ssp_pio_words[0] = ctrl0;
ssp->ssp_pio_words[1] = cmd0;
ssp->ssp_pio_words[2] = cmd1;
ssp->dma_dir = DMA_NONE;
ssp->slave_dirn = DMA_TRANS_NONE;
desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK);
if (!desc)
goto out;

dmaengine_submit(desc);
dma_async_issue_pending(host->dmach);
dma_async_issue_pending(ssp->dmach);
return;

out:
Expand Down Expand Up @@ -441,26 +436,26 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
writel(val, ssp->base + HW_SSP_TIMING(ssp));

/* pio */
host->ssp_pio_words[0] = ctrl0;
host->ssp_pio_words[1] = cmd0;
host->ssp_pio_words[2] = cmd1;
host->dma_dir = DMA_NONE;
host->slave_dirn = DMA_TRANS_NONE;
ssp->ssp_pio_words[0] = ctrl0;
ssp->ssp_pio_words[1] = cmd0;
ssp->ssp_pio_words[2] = cmd1;
ssp->dma_dir = DMA_NONE;
ssp->slave_dirn = DMA_TRANS_NONE;
desc = mxs_mmc_prep_dma(host, 0);
if (!desc)
goto out;

/* append data sg */
WARN_ON(host->data != NULL);
host->data = data;
host->dma_dir = dma_data_dir;
host->slave_dirn = slave_dirn;
ssp->dma_dir = dma_data_dir;
ssp->slave_dirn = slave_dirn;
desc = mxs_mmc_prep_dma(host, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc)
goto out;

dmaengine_submit(desc);
dma_async_issue_pending(host->dmach);
dma_async_issue_pending(ssp->dmach);
return;
out:
dev_warn(mmc_dev(host->mmc),
Expand Down Expand Up @@ -557,14 +552,15 @@ static const struct mmc_host_ops mxs_mmc_ops = {
static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param)
{
struct mxs_mmc_host *host = param;
struct mxs_ssp *ssp = &host->ssp;

if (!mxs_dma_is_apbh(chan))
return false;

if (chan->chan_id != host->dma_channel)
if (chan->chan_id != ssp->dma_channel)
return false;

chan->private = &host->dma_data;
chan->private = &ssp->dma_data;

return true;
}
Expand Down Expand Up @@ -632,15 +628,15 @@ static int mxs_mmc_probe(struct platform_device *pdev)
* to use generic DMA binding later when the helpers get in.
*/
ret = of_property_read_u32(np, "fsl,ssp-dma-channel",
&host->dma_channel);
&ssp->dma_channel);
if (ret) {
dev_err(mmc_dev(host->mmc),
"failed to get dma channel\n");
goto out_mmc_free;
}
} else {
ssp->devid = pdev->id_entry->driver_data;
host->dma_channel = dmares->start;
ssp->dma_channel = dmares->start;
}

host->mmc = mmc;
Expand Down Expand Up @@ -673,9 +669,9 @@ static int mxs_mmc_probe(struct platform_device *pdev)

dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
host->dma_data.chan_irq = irq_dma;
host->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host);
if (!host->dmach) {
ssp->dma_data.chan_irq = irq_dma;
ssp->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host);
if (!ssp->dmach) {
dev_err(mmc_dev(host->mmc),
"%s: failed to request dma\n", __func__);
goto out_clk_put;
Expand Down Expand Up @@ -714,7 +710,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
mmc->max_blk_size = 1 << 0xf;
mmc->max_blk_count = (ssp_is_old(ssp)) ? 0xff : 0xffffff;
mmc->max_req_size = (ssp_is_old(ssp)) ? 0xffff : 0xffffffff;
mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev);
mmc->max_seg_size = dma_get_max_seg_size(ssp->dmach->device->dev);

platform_set_drvdata(pdev, mmc);

Expand All @@ -734,8 +730,8 @@ static int mxs_mmc_probe(struct platform_device *pdev)
return 0;

out_free_dma:
if (host->dmach)
dma_release_channel(host->dmach);
if (ssp->dmach)
dma_release_channel(ssp->dmach);
out_clk_put:
clk_disable_unprepare(ssp->clk);
clk_put(ssp->clk);
Expand All @@ -754,8 +750,8 @@ static int mxs_mmc_remove(struct platform_device *pdev)

platform_set_drvdata(pdev, NULL);

if (host->dmach)
dma_release_channel(host->dmach);
if (ssp->dmach)
dma_release_channel(ssp->dmach);

clk_disable_unprepare(ssp->clk);
clk_put(ssp->clk);
Expand Down
1 change: 0 additions & 1 deletion drivers/spi/spi-mxs.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>
#include <linux/fsl/mxs-dma.h>
#include <linux/pinctrl/consumer.h>
#include <linux/stmp_device.h>
#include <linux/spi/spi.h>
Expand Down
9 changes: 9 additions & 0 deletions include/linux/spi/mxs-spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#ifndef __LINUX_SPI_MXS_SPI_H__
#define __LINUX_SPI_MXS_SPI_H__

#include <linux/fsl/mxs-dma.h>

#define ssp_is_old(host) ((host)->devid == IMX23_SSP)

/* SSP registers */
Expand Down Expand Up @@ -134,6 +136,13 @@ struct mxs_ssp {
struct clk *clk;
unsigned int clk_rate;
enum mxs_ssp_id devid;

int dma_channel;
struct dma_chan *dmach;
struct mxs_dma_data dma_data;
unsigned int dma_dir;
enum dma_transfer_direction slave_dirn;
u32 ssp_pio_words[SSP_PIO_NUM];
};

void mxs_ssp_set_clk_rate(struct mxs_ssp *ssp, unsigned int rate);
Expand Down

0 comments on commit 65defb9

Please sign in to comment.