mmc: mmci: add dma_start callback

This patch adds dma_start callback to mmci_host_ops.
Create a generic mmci_dma_start function which regroup
common action between variant.

Signed-off-by: Ludovic Barre <ludovic.barre@st.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
Ludovic Barre 2018-10-08 14:08:38 +02:00 committed by Ulf Hansson
parent 02769968d9
commit 135ea30e23
3 changed files with 42 additions and 30 deletions

View File

@ -425,6 +425,41 @@ void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data)
host->ops->get_next_data(host, data); host->ops->get_next_data(host, data);
} }
int mmci_dma_start(struct mmci_host *host, unsigned int datactrl)
{
struct mmc_data *data = host->data;
int ret;
if (!host->use_dma)
return -EINVAL;
ret = mmci_prep_data(host, data, false);
if (ret)
return ret;
if (!host->ops || !host->ops->dma_start)
return -EINVAL;
/* Okay, go for it. */
dev_vdbg(mmc_dev(host->mmc),
"Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n",
data->sg_len, data->blksz, data->blocks, data->flags);
host->ops->dma_start(host, &datactrl);
/* Trigger the DMA transfer */
mmci_write_datactrlreg(host, datactrl);
/*
* Let the MMCI say when the data is ended and it's time
* to fire next DMA request. When that happens, MMCI will
* call mmci_data_end()
*/
writel(readl(host->base + MMCIMASK0) | MCI_DATAENDMASK,
host->base + MMCIMASK0);
return 0;
}
static void static void
mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
{ {
@ -736,23 +771,11 @@ int mmci_dmae_prep_data(struct mmci_host *host,
&dmae->desc_current); &dmae->desc_current);
} }
static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) int mmci_dmae_start(struct mmci_host *host, unsigned int *datactrl)
{ {
int ret;
struct mmci_dmae_priv *dmae = host->dma_priv; struct mmci_dmae_priv *dmae = host->dma_priv;
struct mmc_data *data = host->data; struct mmc_data *data = host->data;
if (!host->use_dma)
return -EINVAL;
ret = mmci_dmae_prep_data(host, host->data, false);
if (ret)
return ret;
/* Okay, go for it. */
dev_vdbg(mmc_dev(host->mmc),
"Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n",
data->sg_len, data->blksz, data->blocks, data->flags);
host->dma_in_progress = true; host->dma_in_progress = true;
dmaengine_submit(dmae->desc_current); dmaengine_submit(dmae->desc_current);
dma_async_issue_pending(dmae->cur); dma_async_issue_pending(dmae->cur);
@ -760,18 +783,8 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
if (host->variant->qcom_dml) if (host->variant->qcom_dml)
dml_start_xfer(host, data); dml_start_xfer(host, data);
datactrl |= MCI_DPSM_DMAENABLE; *datactrl |= MCI_DPSM_DMAENABLE;
/* Trigger the DMA transfer */
mmci_write_datactrlreg(host, datactrl);
/*
* Let the MMCI say when the data is ended and it's time
* to fire next DMA request. When that happens, MMCI will
* call mmci_data_end()
*/
writel(readl(host->base + MMCIMASK0) | MCI_DATAENDMASK,
host->base + MMCIMASK0);
return 0; return 0;
} }
@ -830,6 +843,7 @@ static struct mmci_host_ops mmci_variant_ops = {
.get_next_data = mmci_dmae_get_next_data, .get_next_data = mmci_dmae_get_next_data,
.dma_setup = mmci_dmae_setup, .dma_setup = mmci_dmae_setup,
.dma_release = mmci_dmae_release, .dma_release = mmci_dmae_release,
.dma_start = mmci_dmae_start,
}; };
void mmci_variant_init(struct mmci_host *host) void mmci_variant_init(struct mmci_host *host)
@ -847,11 +861,6 @@ static inline void mmci_dma_data_error(struct mmci_host *host)
{ {
} }
static inline int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
{
return -ENOSYS;
}
#endif #endif
static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq) static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq)
@ -948,7 +957,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
* Attempt to use DMA operation mode, if this * Attempt to use DMA operation mode, if this
* should fail, fall back to PIO mode * should fail, fall back to PIO mode
*/ */
if (!mmci_dma_start_data(host, datactrl)) if (!mmci_dma_start(host, datactrl))
return; return;
/* IRQ mode, map the SG list for CPU reading/writing */ /* IRQ mode, map the SG list for CPU reading/writing */

View File

@ -280,6 +280,7 @@ struct mmci_host_ops {
void (*get_next_data)(struct mmci_host *host, struct mmc_data *data); void (*get_next_data)(struct mmci_host *host, struct mmc_data *data);
int (*dma_setup)(struct mmci_host *host); int (*dma_setup)(struct mmci_host *host);
void (*dma_release)(struct mmci_host *host); void (*dma_release)(struct mmci_host *host);
int (*dma_start)(struct mmci_host *host, unsigned int *datactrl);
}; };
struct mmci_host { struct mmci_host {
@ -339,4 +340,5 @@ void mmci_dmae_unprep_data(struct mmci_host *host, struct mmc_data *data,
void mmci_dmae_get_next_data(struct mmci_host *host, struct mmc_data *data); void mmci_dmae_get_next_data(struct mmci_host *host, struct mmc_data *data);
int mmci_dmae_setup(struct mmci_host *host); int mmci_dmae_setup(struct mmci_host *host);
void mmci_dmae_release(struct mmci_host *host); void mmci_dmae_release(struct mmci_host *host);
int mmci_dmae_start(struct mmci_host *host, unsigned int *datactrl);

View File

@ -189,6 +189,7 @@ static struct mmci_host_ops qcom_variant_ops = {
.get_next_data = mmci_dmae_get_next_data, .get_next_data = mmci_dmae_get_next_data,
.dma_setup = qcom_dma_setup, .dma_setup = qcom_dma_setup,
.dma_release = mmci_dmae_release, .dma_release = mmci_dmae_release,
.dma_start = mmci_dmae_start,
}; };
void qcom_variant_init(struct mmci_host *host) void qcom_variant_init(struct mmci_host *host)