mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 22:54:05 +08:00
dmaengine: fsl-edma: add drvdata for fsl-edma
There are some differences between vf610 and next i.mx7ulp. Put such differences into static driver data for distinguishing easily at driver level. Change mcf-edma accordingly. Signed-off-by: Robin Gong <yibin.gong@nxp.com> Tested-by: Angelo Dureghello <angelo@sysam.it> Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
fc4a903078
commit
af802728e4
@ -47,7 +47,7 @@ static void fsl_edma_enable_request(struct fsl_edma_chan *fsl_chan)
|
|||||||
struct edma_regs *regs = &fsl_chan->edma->regs;
|
struct edma_regs *regs = &fsl_chan->edma->regs;
|
||||||
u32 ch = fsl_chan->vchan.chan.chan_id;
|
u32 ch = fsl_chan->vchan.chan.chan_id;
|
||||||
|
|
||||||
if (fsl_chan->edma->version == v1) {
|
if (fsl_chan->edma->drvdata->version == v1) {
|
||||||
edma_writeb(fsl_chan->edma, EDMA_SEEI_SEEI(ch), regs->seei);
|
edma_writeb(fsl_chan->edma, EDMA_SEEI_SEEI(ch), regs->seei);
|
||||||
edma_writeb(fsl_chan->edma, ch, regs->serq);
|
edma_writeb(fsl_chan->edma, ch, regs->serq);
|
||||||
} else {
|
} else {
|
||||||
@ -64,7 +64,7 @@ void fsl_edma_disable_request(struct fsl_edma_chan *fsl_chan)
|
|||||||
struct edma_regs *regs = &fsl_chan->edma->regs;
|
struct edma_regs *regs = &fsl_chan->edma->regs;
|
||||||
u32 ch = fsl_chan->vchan.chan.chan_id;
|
u32 ch = fsl_chan->vchan.chan.chan_id;
|
||||||
|
|
||||||
if (fsl_chan->edma->version == v1) {
|
if (fsl_chan->edma->drvdata->version == v1) {
|
||||||
edma_writeb(fsl_chan->edma, ch, regs->cerq);
|
edma_writeb(fsl_chan->edma, ch, regs->cerq);
|
||||||
edma_writeb(fsl_chan->edma, EDMA_CEEI_CEEI(ch), regs->ceei);
|
edma_writeb(fsl_chan->edma, EDMA_CEEI_CEEI(ch), regs->ceei);
|
||||||
} else {
|
} else {
|
||||||
@ -83,8 +83,9 @@ void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
|
|||||||
u32 ch = fsl_chan->vchan.chan.chan_id;
|
u32 ch = fsl_chan->vchan.chan.chan_id;
|
||||||
void __iomem *muxaddr;
|
void __iomem *muxaddr;
|
||||||
unsigned int chans_per_mux, ch_off;
|
unsigned int chans_per_mux, ch_off;
|
||||||
|
u32 dmamux_nr = fsl_chan->edma->drvdata->dmamuxs;
|
||||||
|
|
||||||
chans_per_mux = fsl_chan->edma->n_chans / DMAMUX_NR;
|
chans_per_mux = fsl_chan->edma->n_chans / dmamux_nr;
|
||||||
ch_off = fsl_chan->vchan.chan.chan_id % chans_per_mux;
|
ch_off = fsl_chan->vchan.chan.chan_id % chans_per_mux;
|
||||||
muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux];
|
muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux];
|
||||||
slot = EDMAMUX_CHCFG_SOURCE(slot);
|
slot = EDMAMUX_CHCFG_SOURCE(slot);
|
||||||
@ -647,28 +648,28 @@ void fsl_edma_setup_regs(struct fsl_edma_engine *edma)
|
|||||||
edma->regs.erql = edma->membase + EDMA_ERQ;
|
edma->regs.erql = edma->membase + EDMA_ERQ;
|
||||||
edma->regs.eeil = edma->membase + EDMA_EEI;
|
edma->regs.eeil = edma->membase + EDMA_EEI;
|
||||||
|
|
||||||
edma->regs.serq = edma->membase + ((edma->version == v1) ?
|
edma->regs.serq = edma->membase + ((edma->drvdata->version == v1) ?
|
||||||
EDMA_SERQ : EDMA64_SERQ);
|
EDMA_SERQ : EDMA64_SERQ);
|
||||||
edma->regs.cerq = edma->membase + ((edma->version == v1) ?
|
edma->regs.cerq = edma->membase + ((edma->drvdata->version == v1) ?
|
||||||
EDMA_CERQ : EDMA64_CERQ);
|
EDMA_CERQ : EDMA64_CERQ);
|
||||||
edma->regs.seei = edma->membase + ((edma->version == v1) ?
|
edma->regs.seei = edma->membase + ((edma->drvdata->version == v1) ?
|
||||||
EDMA_SEEI : EDMA64_SEEI);
|
EDMA_SEEI : EDMA64_SEEI);
|
||||||
edma->regs.ceei = edma->membase + ((edma->version == v1) ?
|
edma->regs.ceei = edma->membase + ((edma->drvdata->version == v1) ?
|
||||||
EDMA_CEEI : EDMA64_CEEI);
|
EDMA_CEEI : EDMA64_CEEI);
|
||||||
edma->regs.cint = edma->membase + ((edma->version == v1) ?
|
edma->regs.cint = edma->membase + ((edma->drvdata->version == v1) ?
|
||||||
EDMA_CINT : EDMA64_CINT);
|
EDMA_CINT : EDMA64_CINT);
|
||||||
edma->regs.cerr = edma->membase + ((edma->version == v1) ?
|
edma->regs.cerr = edma->membase + ((edma->drvdata->version == v1) ?
|
||||||
EDMA_CERR : EDMA64_CERR);
|
EDMA_CERR : EDMA64_CERR);
|
||||||
edma->regs.ssrt = edma->membase + ((edma->version == v1) ?
|
edma->regs.ssrt = edma->membase + ((edma->drvdata->version == v1) ?
|
||||||
EDMA_SSRT : EDMA64_SSRT);
|
EDMA_SSRT : EDMA64_SSRT);
|
||||||
edma->regs.cdne = edma->membase + ((edma->version == v1) ?
|
edma->regs.cdne = edma->membase + ((edma->drvdata->version == v1) ?
|
||||||
EDMA_CDNE : EDMA64_CDNE);
|
EDMA_CDNE : EDMA64_CDNE);
|
||||||
edma->regs.intl = edma->membase + ((edma->version == v1) ?
|
edma->regs.intl = edma->membase + ((edma->drvdata->version == v1) ?
|
||||||
EDMA_INTR : EDMA64_INTL);
|
EDMA_INTR : EDMA64_INTL);
|
||||||
edma->regs.errl = edma->membase + ((edma->version == v1) ?
|
edma->regs.errl = edma->membase + ((edma->drvdata->version == v1) ?
|
||||||
EDMA_ERR : EDMA64_ERRL);
|
EDMA_ERR : EDMA64_ERRL);
|
||||||
|
|
||||||
if (edma->version == v2) {
|
if (edma->drvdata->version == v2) {
|
||||||
edma->regs.erqh = edma->membase + EDMA64_ERQH;
|
edma->regs.erqh = edma->membase + EDMA64_ERQH;
|
||||||
edma->regs.eeih = edma->membase + EDMA64_EEIH;
|
edma->regs.eeih = edma->membase + EDMA64_EEIH;
|
||||||
edma->regs.errh = edma->membase + EDMA64_ERRH;
|
edma->regs.errh = edma->membase + EDMA64_ERRH;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#define _FSL_EDMA_COMMON_H_
|
#define _FSL_EDMA_COMMON_H_
|
||||||
|
|
||||||
#include <linux/dma-direction.h>
|
#include <linux/dma-direction.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
#include "virt-dma.h"
|
#include "virt-dma.h"
|
||||||
|
|
||||||
#define EDMA_CR_EDBG BIT(1)
|
#define EDMA_CR_EDBG BIT(1)
|
||||||
@ -140,17 +141,24 @@ enum edma_version {
|
|||||||
v2, /* 64ch Coldfire */
|
v2, /* 64ch Coldfire */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fsl_edma_drvdata {
|
||||||
|
enum edma_version version;
|
||||||
|
u32 dmamuxs;
|
||||||
|
int (*setup_irq)(struct platform_device *pdev,
|
||||||
|
struct fsl_edma_engine *fsl_edma);
|
||||||
|
};
|
||||||
|
|
||||||
struct fsl_edma_engine {
|
struct fsl_edma_engine {
|
||||||
struct dma_device dma_dev;
|
struct dma_device dma_dev;
|
||||||
void __iomem *membase;
|
void __iomem *membase;
|
||||||
void __iomem *muxbase[DMAMUX_NR];
|
void __iomem *muxbase[DMAMUX_NR];
|
||||||
struct clk *muxclk[DMAMUX_NR];
|
struct clk *muxclk[DMAMUX_NR];
|
||||||
struct mutex fsl_edma_mutex;
|
struct mutex fsl_edma_mutex;
|
||||||
|
const struct fsl_edma_drvdata *drvdata;
|
||||||
u32 n_chans;
|
u32 n_chans;
|
||||||
int txirq;
|
int txirq;
|
||||||
int errirq;
|
int errirq;
|
||||||
bool big_endian;
|
bool big_endian;
|
||||||
enum edma_version version;
|
|
||||||
struct edma_regs regs;
|
struct edma_regs regs;
|
||||||
struct fsl_edma_chan chans[];
|
struct fsl_edma_chan chans[];
|
||||||
};
|
};
|
||||||
|
@ -96,7 +96,8 @@ static struct dma_chan *fsl_edma_xlate(struct of_phandle_args *dma_spec,
|
|||||||
struct fsl_edma_engine *fsl_edma = ofdma->of_dma_data;
|
struct fsl_edma_engine *fsl_edma = ofdma->of_dma_data;
|
||||||
struct dma_chan *chan, *_chan;
|
struct dma_chan *chan, *_chan;
|
||||||
struct fsl_edma_chan *fsl_chan;
|
struct fsl_edma_chan *fsl_chan;
|
||||||
unsigned long chans_per_mux = fsl_edma->n_chans / DMAMUX_NR;
|
u32 dmamux_nr = fsl_edma->drvdata->dmamuxs;
|
||||||
|
unsigned long chans_per_mux = fsl_edma->n_chans / dmamux_nr;
|
||||||
|
|
||||||
if (dma_spec->args_count != 2)
|
if (dma_spec->args_count != 2)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -184,16 +185,38 @@ static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma, int nr_clocks)
|
|||||||
clk_disable_unprepare(fsl_edma->muxclk[i]);
|
clk_disable_unprepare(fsl_edma->muxclk[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct fsl_edma_drvdata vf610_data = {
|
||||||
|
.version = v1,
|
||||||
|
.dmamuxs = DMAMUX_NR,
|
||||||
|
.setup_irq = fsl_edma_irq_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id fsl_edma_dt_ids[] = {
|
||||||
|
{ .compatible = "fsl,vf610-edma", .data = &vf610_data},
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
|
||||||
|
|
||||||
static int fsl_edma_probe(struct platform_device *pdev)
|
static int fsl_edma_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
const struct of_device_id *of_id =
|
||||||
|
of_match_device(fsl_edma_dt_ids, &pdev->dev);
|
||||||
struct device_node *np = pdev->dev.of_node;
|
struct device_node *np = pdev->dev.of_node;
|
||||||
struct fsl_edma_engine *fsl_edma;
|
struct fsl_edma_engine *fsl_edma;
|
||||||
|
const struct fsl_edma_drvdata *drvdata = NULL;
|
||||||
struct fsl_edma_chan *fsl_chan;
|
struct fsl_edma_chan *fsl_chan;
|
||||||
struct edma_regs *regs;
|
struct edma_regs *regs;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
int len, chans;
|
int len, chans;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
|
if (of_id)
|
||||||
|
drvdata = of_id->data;
|
||||||
|
if (!drvdata) {
|
||||||
|
dev_err(&pdev->dev, "unable to find driver data\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
ret = of_property_read_u32(np, "dma-channels", &chans);
|
ret = of_property_read_u32(np, "dma-channels", &chans);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Can't get dma-channels.\n");
|
dev_err(&pdev->dev, "Can't get dma-channels.\n");
|
||||||
@ -205,7 +228,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
|
|||||||
if (!fsl_edma)
|
if (!fsl_edma)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
fsl_edma->version = v1;
|
fsl_edma->drvdata = drvdata;
|
||||||
fsl_edma->n_chans = chans;
|
fsl_edma->n_chans = chans;
|
||||||
mutex_init(&fsl_edma->fsl_edma_mutex);
|
mutex_init(&fsl_edma->fsl_edma_mutex);
|
||||||
|
|
||||||
@ -217,7 +240,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
|
|||||||
fsl_edma_setup_regs(fsl_edma);
|
fsl_edma_setup_regs(fsl_edma);
|
||||||
regs = &fsl_edma->regs;
|
regs = &fsl_edma->regs;
|
||||||
|
|
||||||
for (i = 0; i < DMAMUX_NR; i++) {
|
for (i = 0; i < fsl_edma->drvdata->dmamuxs; i++) {
|
||||||
char clkname[32];
|
char clkname[32];
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
|
||||||
@ -263,7 +286,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
edma_writel(fsl_edma, ~0, regs->intl);
|
edma_writel(fsl_edma, ~0, regs->intl);
|
||||||
ret = fsl_edma_irq_init(pdev, fsl_edma);
|
ret = fsl_edma->drvdata->setup_irq(pdev, fsl_edma);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -295,7 +318,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"Can't register Freescale eDMA engine. (%d)\n", ret);
|
"Can't register Freescale eDMA engine. (%d)\n", ret);
|
||||||
fsl_disable_clocks(fsl_edma, DMAMUX_NR);
|
fsl_disable_clocks(fsl_edma, fsl_edma->drvdata->dmamuxs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +327,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
|
|||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"Can't register Freescale eDMA of_dma. (%d)\n", ret);
|
"Can't register Freescale eDMA of_dma. (%d)\n", ret);
|
||||||
dma_async_device_unregister(&fsl_edma->dma_dev);
|
dma_async_device_unregister(&fsl_edma->dma_dev);
|
||||||
fsl_disable_clocks(fsl_edma, DMAMUX_NR);
|
fsl_disable_clocks(fsl_edma, fsl_edma->drvdata->dmamuxs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,7 +346,7 @@ static int fsl_edma_remove(struct platform_device *pdev)
|
|||||||
fsl_edma_cleanup_vchan(&fsl_edma->dma_dev);
|
fsl_edma_cleanup_vchan(&fsl_edma->dma_dev);
|
||||||
of_dma_controller_free(np);
|
of_dma_controller_free(np);
|
||||||
dma_async_device_unregister(&fsl_edma->dma_dev);
|
dma_async_device_unregister(&fsl_edma->dma_dev);
|
||||||
fsl_disable_clocks(fsl_edma, DMAMUX_NR);
|
fsl_disable_clocks(fsl_edma, fsl_edma->drvdata->dmamuxs);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -382,12 +405,6 @@ static const struct dev_pm_ops fsl_edma_pm_ops = {
|
|||||||
.resume_early = fsl_edma_resume_early,
|
.resume_early = fsl_edma_resume_early,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id fsl_edma_dt_ids[] = {
|
|
||||||
{ .compatible = "fsl,vf610-edma", },
|
|
||||||
{ /* sentinel */ }
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
|
|
||||||
|
|
||||||
static struct platform_driver fsl_edma_driver = {
|
static struct platform_driver fsl_edma_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "fsl-edma",
|
.name = "fsl-edma",
|
||||||
|
@ -164,6 +164,11 @@ static void mcf_edma_irq_free(struct platform_device *pdev,
|
|||||||
free_irq(irq, mcf_edma);
|
free_irq(irq, mcf_edma);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct fsl_edma_drvdata mcf_data = {
|
||||||
|
.version = v2,
|
||||||
|
.setup_irq = mcf_edma_irq_init,
|
||||||
|
};
|
||||||
|
|
||||||
static int mcf_edma_probe(struct platform_device *pdev)
|
static int mcf_edma_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct mcf_edma_platform_data *pdata;
|
struct mcf_edma_platform_data *pdata;
|
||||||
@ -187,8 +192,8 @@ static int mcf_edma_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
mcf_edma->n_chans = chans;
|
mcf_edma->n_chans = chans;
|
||||||
|
|
||||||
/* Set up version for ColdFire edma */
|
/* Set up drvdata for ColdFire edma */
|
||||||
mcf_edma->version = v2;
|
mcf_edma->drvdata = &mcf_data;
|
||||||
mcf_edma->big_endian = 1;
|
mcf_edma->big_endian = 1;
|
||||||
|
|
||||||
if (!mcf_edma->n_chans) {
|
if (!mcf_edma->n_chans) {
|
||||||
@ -223,7 +228,7 @@ static int mcf_edma_probe(struct platform_device *pdev)
|
|||||||
iowrite32(~0, regs->inth);
|
iowrite32(~0, regs->inth);
|
||||||
iowrite32(~0, regs->intl);
|
iowrite32(~0, regs->intl);
|
||||||
|
|
||||||
ret = mcf_edma_irq_init(pdev, mcf_edma);
|
ret = mcf_edma->drvdata->setup_irq(pdev, mcf_edma);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user