Skip to content

Commit

Permalink
dw_dmac: add ACPI support
Browse files Browse the repository at this point in the history
Since we have proper ACPI DMA helpers implemented, the driver may use it. This
patch introduces custom filter function together with acpi_device_id table.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
  • Loading branch information
Andy Shevchenko authored and Vinod Koul committed Apr 15, 2013
1 parent 4e82f5d commit 42c91ee
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 19 deletions.
68 changes: 50 additions & 18 deletions drivers/dma/dw_dmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/acpi_dma.h>

#include "dw_dmac_regs.h"
#include "dmaengine.h"
Expand Down Expand Up @@ -983,13 +985,6 @@ static inline void convert_burst(u32 *maxburst)
*maxburst = 0;
}

static inline void convert_slave_id(struct dw_dma_chan *dwc)
{
struct dw_dma *dw = to_dw_dma(dwc->chan.device);

dwc->dma_sconfig.slave_id -= dw->request_line_base;
}

static int
set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
{
Expand All @@ -1008,7 +1003,6 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)

convert_burst(&dwc->dma_sconfig.src_maxburst);
convert_burst(&dwc->dma_sconfig.dst_maxburst);
convert_slave_id(dwc);

return 0;
}
Expand Down Expand Up @@ -1284,6 +1278,46 @@ static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec,
return dma_request_channel(cap, dw_dma_of_filter, &fargs);
}

#ifdef CONFIG_ACPI
static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param)
{
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
struct acpi_dma_spec *dma_spec = param;

if (chan->device->dev != dma_spec->dev ||
chan->chan_id != dma_spec->chan_id)
return false;

dwc->request_line = dma_spec->slave_id;
dwc->src_master = dwc_get_sms(NULL);
dwc->dst_master = dwc_get_dms(NULL);

return true;
}

static void dw_dma_acpi_controller_register(struct dw_dma *dw)
{
struct device *dev = dw->dma.dev;
struct acpi_dma_filter_info *info;
int ret;

info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
if (!info)
return;

dma_cap_zero(info->dma_cap);
dma_cap_set(DMA_SLAVE, info->dma_cap);
info->filter_fn = dw_dma_acpi_filter;

ret = devm_acpi_dma_controller_register(dev, acpi_dma_simple_xlate,
info);
if (ret)
dev_err(dev, "could not register acpi_dma_controller\n");
}
#else /* !CONFIG_ACPI */
static inline void dw_dma_acpi_controller_register(struct dw_dma *dw) {}
#endif /* !CONFIG_ACPI */

/* --------------------- Cyclic DMA API extensions -------------------- */

/**
Expand Down Expand Up @@ -1620,7 +1654,6 @@ dw_dma_parse_dt(struct platform_device *pdev)

static int dw_probe(struct platform_device *pdev)
{
const struct platform_device_id *match;
struct dw_dma_platform_data *pdata;
struct resource *io;
struct dw_dma *dw;
Expand Down Expand Up @@ -1704,11 +1737,6 @@ static int dw_probe(struct platform_device *pdev)
memcpy(dw->data_width, pdata->data_width, 4);
}

/* Get the base request line if set */
match = platform_get_device_id(pdev);
if (match)
dw->request_line_base = (unsigned int)match->driver_data;

/* Calculate all channel mask before DMA setup */
dw->all_chan_mask = (1 << nr_channels) - 1;

Expand Down Expand Up @@ -1833,6 +1861,9 @@ static int dw_probe(struct platform_device *pdev)
"could not register of_dma_controller\n");
}

if (ACPI_HANDLE(&pdev->dev))
dw_dma_acpi_controller_register(dw);

return 0;
}

Expand Down Expand Up @@ -1904,11 +1935,12 @@ static const struct of_device_id dw_dma_of_id_table[] = {
MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
#endif

static const struct platform_device_id dw_dma_ids[] = {
/* Name, Request Line Base */
{ "INTL9C60", (kernel_ulong_t)16 },
#ifdef CONFIG_ACPI
static const struct acpi_device_id dw_dma_acpi_id_table[] = {
{ "INTL9C60", 0 },
{ }
};
#endif

static struct platform_driver dw_driver = {
.probe = dw_probe,
Expand All @@ -1918,8 +1950,8 @@ static struct platform_driver dw_driver = {
.name = "dw_dmac",
.pm = &dw_dev_pm_ops,
.of_match_table = of_match_ptr(dw_dma_of_id_table),
.acpi_match_table = ACPI_PTR(dw_dma_acpi_id_table),
},
.id_table = dw_dma_ids,
};

static int __init dw_init(void)
Expand Down
1 change: 0 additions & 1 deletion drivers/dma/dw_dmac_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,6 @@ struct dw_dma {
/* hardware configuration */
unsigned char nr_masters;
unsigned char data_width[4];
unsigned int request_line_base;

struct dw_dma_chan chan[0];
};
Expand Down

0 comments on commit 42c91ee

Please sign in to comment.