Commit 631fa73c authored by Simon Horman's avatar Simon Horman Committed by Ulf Hansson

mmc: renesas-sdhi, tmio: make dma more modular

Refactor DMA support to allow it to be provided by a set of call-backs
that are provided by a host driver. The motivation is to allow multiple
DMA implementations to be provided and instantiated at run-time.

Instantiate the existing DMA implementation from the sh_mobile_sdhi driver
which appears to match the current use-case. This has the side effect
of moving the DMA code from the tmio_core to the sh_mobile_sdhi driver.

A follow-up patch will change the source file for the SDHI DMA
implementation accordingly. Another follow-up patch will re-organise the
SDHI driver removing the need for tmio_mmc_get_dma_ops().
Signed-off-by: default avatarSimon Horman <horms+renesas@verge.net.au>
Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
Reviewed-by: default avatarWolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent b21f13d8
...@@ -37,8 +37,7 @@ obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o ...@@ -37,8 +37,7 @@ obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o
obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
obj-$(CONFIG_MMC_TMIO_CORE) += tmio_mmc_core.o obj-$(CONFIG_MMC_TMIO_CORE) += tmio_mmc_core.o
tmio_mmc_core-y := tmio_mmc_pio.o tmio_mmc_core-y := tmio_mmc_pio.o
tmio_mmc_core-$(subst m,y,$(CONFIG_MMC_SDHI)) += tmio_mmc_dma.o obj-$(CONFIG_MMC_SDHI) += sh_mobile_sdhi.o tmio_mmc_dma.o
obj-$(CONFIG_MMC_SDHI) += sh_mobile_sdhi.o
obj-$(CONFIG_MMC_CB710) += cb710-mmc.o obj-$(CONFIG_MMC_CB710) += cb710-mmc.o
obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o
obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o
......
...@@ -667,7 +667,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) ...@@ -667,7 +667,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
/* All SDHI have SDIO status bits which must be 1 */ /* All SDHI have SDIO status bits which must be 1 */
mmc_data->flags |= TMIO_MMC_SDIO_STATUS_SETBITS; mmc_data->flags |= TMIO_MMC_SDIO_STATUS_SETBITS;
ret = tmio_mmc_host_probe(host, mmc_data); ret = tmio_mmc_host_probe(host, mmc_data, tmio_mmc_get_dma_ops());
if (ret < 0) if (ret < 0)
goto efree; goto efree;
......
...@@ -97,7 +97,7 @@ static int tmio_mmc_probe(struct platform_device *pdev) ...@@ -97,7 +97,7 @@ static int tmio_mmc_probe(struct platform_device *pdev)
/* SD control register space size is 0x200, 0x400 for bus_shift=1 */ /* SD control register space size is 0x200, 0x400 for bus_shift=1 */
host->bus_shift = resource_size(res) >> 10; host->bus_shift = resource_size(res) >> 10;
ret = tmio_mmc_host_probe(host, pdata); ret = tmio_mmc_host_probe(host, pdata, NULL);
if (ret) if (ret)
goto host_free; goto host_free;
......
...@@ -114,6 +114,15 @@ struct tmio_mmc_dma { ...@@ -114,6 +114,15 @@ struct tmio_mmc_dma {
void (*enable)(struct tmio_mmc_host *host, bool enable); void (*enable)(struct tmio_mmc_host *host, bool enable);
}; };
struct tmio_mmc_dma_ops {
void (*start)(struct tmio_mmc_host *host, struct mmc_data *data);
void (*enable)(struct tmio_mmc_host *host, bool enable);
void (*request)(struct tmio_mmc_host *host,
struct tmio_mmc_data *pdata);
void (*release)(struct tmio_mmc_host *host);
void (*abort)(struct tmio_mmc_host *host);
};
struct tmio_mmc_host { struct tmio_mmc_host {
void __iomem *ctl; void __iomem *ctl;
struct mmc_command *cmd; struct mmc_command *cmd;
...@@ -188,12 +197,15 @@ struct tmio_mmc_host { ...@@ -188,12 +197,15 @@ struct tmio_mmc_host {
/* Tuning values: 1 for success, 0 for failure */ /* Tuning values: 1 for success, 0 for failure */
DECLARE_BITMAP(taps, BITS_PER_BYTE * sizeof(long)); DECLARE_BITMAP(taps, BITS_PER_BYTE * sizeof(long));
unsigned int tap_num; unsigned int tap_num;
const struct tmio_mmc_dma_ops *dma_ops;
}; };
struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev); struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev);
void tmio_mmc_host_free(struct tmio_mmc_host *host); void tmio_mmc_host_free(struct tmio_mmc_host *host);
int tmio_mmc_host_probe(struct tmio_mmc_host *host, int tmio_mmc_host_probe(struct tmio_mmc_host *host,
struct tmio_mmc_data *pdata); struct tmio_mmc_data *pdata,
const struct tmio_mmc_dma_ops *dma_ops);
void tmio_mmc_host_remove(struct tmio_mmc_host *host); void tmio_mmc_host_remove(struct tmio_mmc_host *host);
void tmio_mmc_do_data_irq(struct tmio_mmc_host *host); void tmio_mmc_do_data_irq(struct tmio_mmc_host *host);
...@@ -201,6 +213,15 @@ void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i); ...@@ -201,6 +213,15 @@ void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i); void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
irqreturn_t tmio_mmc_irq(int irq, void *devid); irqreturn_t tmio_mmc_irq(int irq, void *devid);
#if IS_ENABLED(CONFIG_MMC_SDHI)
const struct tmio_mmc_dma_ops *tmio_mmc_get_dma_ops(void);
#else
static inline const struct tmio_mmc_dma_ops *tmio_mmc_get_dma_ops(void)
{
return NULL;
}
#endif
static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg,
unsigned long *flags) unsigned long *flags)
{ {
...@@ -215,38 +236,6 @@ static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg, ...@@ -215,38 +236,6 @@ static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg,
local_irq_restore(*flags); local_irq_restore(*flags);
} }
#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data);
void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable);
void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata);
void tmio_mmc_release_dma(struct tmio_mmc_host *host);
void tmio_mmc_abort_dma(struct tmio_mmc_host *host);
#else
static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host,
struct mmc_data *data)
{
}
static inline void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
{
}
static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host,
struct tmio_mmc_data *pdata)
{
host->chan_tx = NULL;
host->chan_rx = NULL;
}
static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host)
{
}
static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host)
{
}
#endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
int tmio_mmc_host_runtime_suspend(struct device *dev); int tmio_mmc_host_runtime_suspend(struct device *dev);
int tmio_mmc_host_runtime_resume(struct device *dev); int tmio_mmc_host_runtime_resume(struct device *dev);
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#define TMIO_MMC_MIN_DMA_LEN 8 #define TMIO_MMC_MIN_DMA_LEN 8
void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
{ {
if (!host->chan_tx || !host->chan_rx) if (!host->chan_tx || !host->chan_rx)
return; return;
...@@ -29,7 +29,7 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) ...@@ -29,7 +29,7 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
host->dma->enable(host, enable); host->dma->enable(host, enable);
} }
void tmio_mmc_abort_dma(struct tmio_mmc_host *host) static void tmio_mmc_abort_dma(struct tmio_mmc_host *host)
{ {
tmio_mmc_enable_dma(host, false); tmio_mmc_enable_dma(host, false);
...@@ -221,7 +221,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) ...@@ -221,7 +221,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
} }
} }
void tmio_mmc_start_dma(struct tmio_mmc_host *host, static void tmio_mmc_start_dma(struct tmio_mmc_host *host,
struct mmc_data *data) struct mmc_data *data)
{ {
if (data->flags & MMC_DATA_READ) { if (data->flags & MMC_DATA_READ) {
...@@ -255,7 +255,8 @@ static void tmio_mmc_issue_tasklet_fn(unsigned long priv) ...@@ -255,7 +255,8 @@ static void tmio_mmc_issue_tasklet_fn(unsigned long priv)
dma_async_issue_pending(chan); dma_async_issue_pending(chan);
} }
void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata) static void tmio_mmc_request_dma(struct tmio_mmc_host *host,
struct tmio_mmc_data *pdata)
{ {
/* We can only either use DMA for both Tx and Rx or not use it at all */ /* We can only either use DMA for both Tx and Rx or not use it at all */
if (!host->dma || (!host->pdev->dev.of_node && if (!host->dma || (!host->pdev->dev.of_node &&
...@@ -335,7 +336,7 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat ...@@ -335,7 +336,7 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat
host->chan_tx = NULL; host->chan_tx = NULL;
} }
void tmio_mmc_release_dma(struct tmio_mmc_host *host) static void tmio_mmc_release_dma(struct tmio_mmc_host *host)
{ {
if (host->chan_tx) { if (host->chan_tx) {
struct dma_chan *chan = host->chan_tx; struct dma_chan *chan = host->chan_tx;
...@@ -352,3 +353,16 @@ void tmio_mmc_release_dma(struct tmio_mmc_host *host) ...@@ -352,3 +353,16 @@ void tmio_mmc_release_dma(struct tmio_mmc_host *host)
host->bounce_buf = NULL; host->bounce_buf = NULL;
} }
} }
static const struct tmio_mmc_dma_ops tmio_mmc_dma_ops = {
.start = tmio_mmc_start_dma,
.enable = tmio_mmc_enable_dma,
.request = tmio_mmc_request_dma,
.release = tmio_mmc_release_dma,
.abort = tmio_mmc_abort_dma,
};
const struct tmio_mmc_dma_ops *tmio_mmc_get_dma_ops(void)
{
return &tmio_mmc_dma_ops;
}
...@@ -50,17 +50,55 @@ ...@@ -50,17 +50,55 @@
#include "tmio_mmc.h" #include "tmio_mmc.h"
static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host,
struct mmc_data *data)
{
if (host->dma_ops)
host->dma_ops->start(host, data);
}
static inline void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
{
if (host->dma_ops)
host->dma_ops->enable(host, enable);
}
static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host,
struct tmio_mmc_data *pdata)
{
if (host->dma_ops) {
host->dma_ops->request(host, pdata);
} else {
host->chan_tx = NULL;
host->chan_rx = NULL;
}
}
static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host)
{
if (host->dma_ops)
host->dma_ops->release(host);
}
static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host)
{
if (host->dma_ops)
host->dma_ops->abort(host);
}
void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i) void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i)
{ {
host->sdcard_irq_mask &= ~(i & TMIO_MASK_IRQ); host->sdcard_irq_mask &= ~(i & TMIO_MASK_IRQ);
sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask); sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask);
} }
EXPORT_SYMBOL(tmio_mmc_enable_mmc_irqs);
void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i) void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i)
{ {
host->sdcard_irq_mask |= (i & TMIO_MASK_IRQ); host->sdcard_irq_mask |= (i & TMIO_MASK_IRQ);
sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask); sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask);
} }
EXPORT_SYMBOL(tmio_mmc_disable_mmc_irqs);
static void tmio_mmc_ack_mmc_irqs(struct tmio_mmc_host *host, u32 i) static void tmio_mmc_ack_mmc_irqs(struct tmio_mmc_host *host, u32 i)
{ {
...@@ -563,6 +601,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host) ...@@ -563,6 +601,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
schedule_work(&host->done); schedule_work(&host->done);
} }
EXPORT_SYMBOL(tmio_mmc_do_data_irq);
static void tmio_mmc_data_irq(struct tmio_mmc_host *host, unsigned int stat) static void tmio_mmc_data_irq(struct tmio_mmc_host *host, unsigned int stat)
{ {
...@@ -1138,7 +1177,8 @@ void tmio_mmc_host_free(struct tmio_mmc_host *host) ...@@ -1138,7 +1177,8 @@ void tmio_mmc_host_free(struct tmio_mmc_host *host)
EXPORT_SYMBOL(tmio_mmc_host_free); EXPORT_SYMBOL(tmio_mmc_host_free);
int tmio_mmc_host_probe(struct tmio_mmc_host *_host, int tmio_mmc_host_probe(struct tmio_mmc_host *_host,
struct tmio_mmc_data *pdata) struct tmio_mmc_data *pdata,
const struct tmio_mmc_dma_ops *dma_ops)
{ {
struct platform_device *pdev = _host->pdev; struct platform_device *pdev = _host->pdev;
struct mmc_host *mmc = _host->mmc; struct mmc_host *mmc = _host->mmc;
...@@ -1250,6 +1290,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host, ...@@ -1250,6 +1290,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host,
INIT_WORK(&_host->done, tmio_mmc_done_work); INIT_WORK(&_host->done, tmio_mmc_done_work);
/* See if we also get DMA */ /* See if we also get DMA */
_host->dma_ops = dma_ops;
tmio_mmc_request_dma(_host, pdata); tmio_mmc_request_dma(_host, pdata);
pm_runtime_set_active(&pdev->dev); pm_runtime_set_active(&pdev->dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment