From 39416677b95bf1ab8bbfa229ec7e511c96ad5d0c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 28 Sep 2015 18:57:04 +0300 Subject: dmaengine: dw: convert to __ffs() We replace __fls() by __ffs() since we have to find a *minimum* data width that satisfies both source and destination. While here, rename dwc_fast_fls() to dwc_fast_ffs() which it really is. Fixes: 4c2d56c574db (dw_dmac: introduce dwc_fast_fls()) Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/dma/dw') diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index cf1c87fa1edd..46859f738fcf 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -163,7 +163,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc) /*----------------------------------------------------------------------*/ -static inline unsigned int dwc_fast_fls(unsigned long long v) +static inline unsigned int dwc_fast_ffs(unsigned long long v) { /* * We can be a lot more clever here, but this should take care @@ -712,7 +712,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, dw->data_width[dwc->dst_master]); src_width = dst_width = min_t(unsigned int, data_width, - dwc_fast_fls(src | dest | len)); + dwc_fast_ffs(src | dest | len)); ctllo = DWC_DEFAULT_CTLLO(chan) | DWC_CTLL_DST_WIDTH(dst_width) @@ -791,7 +791,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, switch (direction) { case DMA_MEM_TO_DEV: - reg_width = __fls(sconfig->dst_addr_width); + reg_width = __ffs(sconfig->dst_addr_width); reg = sconfig->dst_addr; ctllo = (DWC_DEFAULT_CTLLO(chan) | DWC_CTLL_DST_WIDTH(reg_width) @@ -811,7 +811,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, len = sg_dma_len(sg); mem_width = min_t(unsigned int, - data_width, dwc_fast_fls(mem | len)); + data_width, dwc_fast_ffs(mem | len)); slave_sg_todev_fill_desc: desc = dwc_desc_get(dwc); @@ -848,7 +848,7 @@ slave_sg_todev_fill_desc: } break; case DMA_DEV_TO_MEM: - reg_width = __fls(sconfig->src_addr_width); + reg_width = __ffs(sconfig->src_addr_width); reg = sconfig->src_addr; ctllo = (DWC_DEFAULT_CTLLO(chan) | DWC_CTLL_SRC_WIDTH(reg_width) @@ -868,7 +868,7 @@ slave_sg_todev_fill_desc: len = sg_dma_len(sg); mem_width = min_t(unsigned int, - data_width, dwc_fast_fls(mem | len)); + data_width, dwc_fast_ffs(mem | len)); slave_sg_fromdev_fill_desc: desc = dwc_desc_get(dwc); -- cgit v1.2.3 From 6dbd80a919db24f5a1c66460838bb10ebe188d21 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 28 Sep 2015 18:57:05 +0300 Subject: dmaengine: dw: use dw_dmac autoconfiguration in PCI driver Instead of hardconding a platform data for dw_dmac let's use it's own autoconfiguration feature. Thus, remove hardcoded values. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/pci.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers/dma/dw') diff --git a/drivers/dma/dw/pci.c b/drivers/dma/dw/pci.c index b144706b3d85..4c30fdd092b3 100644 --- a/drivers/dma/dw/pci.c +++ b/drivers/dma/dw/pci.c @@ -15,12 +15,6 @@ #include "internal.h" -static struct dw_dma_platform_data dw_pci_pdata = { - .is_private = 1, - .chan_allocation_order = CHAN_ALLOCATION_ASCENDING, - .chan_priority = CHAN_PRIORITY_ASCENDING, -}; - static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) { struct dw_dma_chip *chip; @@ -101,19 +95,19 @@ static const struct dev_pm_ops dw_pci_dev_pm_ops = { static const struct pci_device_id dw_pci_id_table[] = { /* Medfield */ - { PCI_VDEVICE(INTEL, 0x0827), (kernel_ulong_t)&dw_pci_pdata }, - { PCI_VDEVICE(INTEL, 0x0830), (kernel_ulong_t)&dw_pci_pdata }, + { PCI_VDEVICE(INTEL, 0x0827) }, + { PCI_VDEVICE(INTEL, 0x0830) }, /* BayTrail */ - { PCI_VDEVICE(INTEL, 0x0f06), (kernel_ulong_t)&dw_pci_pdata }, - { PCI_VDEVICE(INTEL, 0x0f40), (kernel_ulong_t)&dw_pci_pdata }, + { PCI_VDEVICE(INTEL, 0x0f06) }, + { PCI_VDEVICE(INTEL, 0x0f40) }, /* Braswell */ - { PCI_VDEVICE(INTEL, 0x2286), (kernel_ulong_t)&dw_pci_pdata }, - { PCI_VDEVICE(INTEL, 0x22c0), (kernel_ulong_t)&dw_pci_pdata }, + { PCI_VDEVICE(INTEL, 0x2286) }, + { PCI_VDEVICE(INTEL, 0x22c0) }, /* Haswell */ - { PCI_VDEVICE(INTEL, 0x9c60), (kernel_ulong_t)&dw_pci_pdata }, + { PCI_VDEVICE(INTEL, 0x9c60) }, { } }; MODULE_DEVICE_TABLE(pci, dw_pci_id_table); -- cgit v1.2.3 From 30cb2639aa5253cf5bc4bd7dc5ea7e61b6887379 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 13 Oct 2015 20:09:17 +0300 Subject: dmaengine: dw: don't override platform data with autocfg Let probe driver decide either it wants to auto configure the driver or have explicitly defined properties. Signed-off-by: Andy Shevchenko Acked-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 57 ++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) (limited to 'drivers/dma/dw') diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 46859f738fcf..f16d1ed99ba9 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -1499,9 +1499,8 @@ EXPORT_SYMBOL(dw_dma_cyclic_free); int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) { struct dw_dma *dw; - bool autocfg; + bool autocfg = false; unsigned int dw_params; - unsigned int nr_channels; unsigned int max_blk_size = 0; int err; int i; @@ -1515,33 +1514,41 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) pm_runtime_get_sync(chip->dev); - dw_params = dma_read_byaddr(chip->regs, DW_PARAMS); - autocfg = dw_params >> DW_PARAMS_EN & 0x1; + if (!pdata) { + dw_params = dma_read_byaddr(chip->regs, DW_PARAMS); + dev_dbg(chip->dev, "DW_PARAMS: 0x%08x\n", dw_params); - dev_dbg(chip->dev, "DW_PARAMS: 0x%08x\n", dw_params); + autocfg = dw_params >> DW_PARAMS_EN & 1; + if (!autocfg) { + err = -EINVAL; + goto err_pdata; + } - if (!pdata && autocfg) { pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { err = -ENOMEM; goto err_pdata; } + /* Get hardware configuration parameters */ + pdata->nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 7) + 1; + pdata->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1; + for (i = 0; i < pdata->nr_masters; i++) { + pdata->data_width[i] = + (dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3) + 2; + } + max_blk_size = dma_readl(dw, MAX_BLK_SIZE); + /* Fill platform data with the default values */ pdata->is_private = true; pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING; pdata->chan_priority = CHAN_PRIORITY_ASCENDING; - } else if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) { + } else if (pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) { err = -EINVAL; goto err_pdata; } - if (autocfg) - nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 0x7) + 1; - else - nr_channels = pdata->nr_channels; - - dw->chan = devm_kcalloc(chip->dev, nr_channels, sizeof(*dw->chan), + dw->chan = devm_kcalloc(chip->dev, pdata->nr_channels, sizeof(*dw->chan), GFP_KERNEL); if (!dw->chan) { err = -ENOMEM; @@ -1549,22 +1556,12 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) } /* Get hardware configuration parameters */ - if (autocfg) { - max_blk_size = dma_readl(dw, MAX_BLK_SIZE); - - dw->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1; - for (i = 0; i < dw->nr_masters; i++) { - dw->data_width[i] = - (dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3) + 2; - } - } else { - dw->nr_masters = pdata->nr_masters; - for (i = 0; i < dw->nr_masters; i++) - dw->data_width[i] = pdata->data_width[i]; - } + dw->nr_masters = pdata->nr_masters; + for (i = 0; i < dw->nr_masters; i++) + dw->data_width[i] = pdata->data_width[i]; /* Calculate all channel mask before DMA setup */ - dw->all_chan_mask = (1 << nr_channels) - 1; + dw->all_chan_mask = (1 << pdata->nr_channels) - 1; /* Force dma off, just in case */ dw_dma_off(dw); @@ -1589,7 +1586,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) goto err_pdata; INIT_LIST_HEAD(&dw->dma.channels); - for (i = 0; i < nr_channels; i++) { + for (i = 0; i < pdata->nr_channels; i++) { struct dw_dma_chan *dwc = &dw->chan[i]; int r = nr_channels - i - 1; @@ -1603,7 +1600,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) /* 7 is highest priority & 0 is lowest. */ if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING) - dwc->priority = r; + dwc->priority = pdata->nr_channels - i - 1; else dwc->priority = i; @@ -1687,7 +1684,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) goto err_dma_register; dev_info(chip->dev, "DesignWare DMA Controller, %d channels\n", - nr_channels); + pdata->nr_channels); pm_runtime_put_sync_suspend(chip->dev); -- cgit v1.2.3 From 175267b389f781748e2bbb6c737e76b5c9bc4c88 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 13 Oct 2015 20:09:18 +0300 Subject: dmaengine: dw: platform: provide platform data for Intel Provide platform data explicitly for Intel SoCs where dw_dmac is enumerated by ACPI. Signed-off-by: Andy Shevchenko Acked-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw/platform.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers/dma/dw') diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index b2c3ae071429..68a4815750b5 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -155,6 +155,7 @@ static int dw_probe(struct platform_device *pdev) struct dw_dma_chip *chip; struct device *dev = &pdev->dev; struct resource *mem; + const struct acpi_device_id *id; struct dw_dma_platform_data *pdata; int err; @@ -178,6 +179,11 @@ static int dw_probe(struct platform_device *pdev) pdata = dev_get_platdata(dev); if (!pdata) pdata = dw_dma_parse_dt(pdev); + if (!pdata && has_acpi_companion(dev)) { + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (id) + pdata = (struct dw_dma_platform_data *)id->driver_data; + } chip->dev = dev; @@ -246,8 +252,17 @@ MODULE_DEVICE_TABLE(of, dw_dma_of_id_table); #endif #ifdef CONFIG_ACPI +static struct dw_dma_platform_data dw_dma_acpi_pdata = { + .nr_channels = 8, + .is_private = true, + .chan_allocation_order = CHAN_ALLOCATION_ASCENDING, + .chan_priority = CHAN_PRIORITY_ASCENDING, + .block_size = 4095, + .nr_masters = 2, +}; + static const struct acpi_device_id dw_dma_acpi_id_table[] = { - { "INTL9C60", 0 }, + { "INTL9C60", (kernel_ulong_t)&dw_dma_acpi_pdata }, { } }; MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table); -- cgit v1.2.3 From df5c7386f62d2db95ca48005087195e9a15e2b1f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 13 Oct 2015 20:09:19 +0300 Subject: dmaengine: dw: some Intel devices has no memcpy support Provide a flag to choose if the device does support memory-to-memory transfers. At least this is not true for iDMA32 controller that might be supported in the future. Besides that Intel BayTrail and Braswell users should not try this feature due to HW specific behaviour. Signed-off-by: Andy Shevchenko Acked-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/dma/dw') diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index f16d1ed99ba9..41e9554b884d 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -1541,6 +1541,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) /* Fill platform data with the default values */ pdata->is_private = true; + pdata->is_memcpy = true; pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING; pdata->chan_priority = CHAN_PRIORITY_ASCENDING; } else if (pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) { @@ -1653,10 +1654,13 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) dma_writel(dw, CLEAR.DST_TRAN, dw->all_chan_mask); dma_writel(dw, CLEAR.ERROR, dw->all_chan_mask); - dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask); + /* Set capabilities */ dma_cap_set(DMA_SLAVE, dw->dma.cap_mask); if (pdata->is_private) dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask); + if (pdata->is_memcpy) + dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask); + dw->dma.dev = chip->dev; dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources; dw->dma.device_free_chan_resources = dwc_free_chan_resources; -- cgit v1.2.3