mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
Merge branch 'tegra/dma-reset-rework' into next/dt
Bringing in the tegra dma/reset framework cleanup as a base for the DT changes. * tegra/dma-reset-rework: (320 commits) spi: tegra: checking for ERR_PTR instead of NULL ASoC: tegra: update module reset list for Tegra124 clk: tegra: remove bogus PCIE_XCLK clk: tegra: remove legacy reset APIs ARM: tegra: remove legacy DMA entries from DT ARM: tegra: remove legacy clock entries from DT USB: EHCI: tegra: use reset framework Input: tegra-kbc - use reset framework serial: tegra: convert to standard DMA DT bindings serial: tegra: use reset framework spi: tegra: convert to standard DMA DT bindings spi: tegra: use reset framework staging: nvec: use reset framework i2c: tegra: use reset framework ASoC: tegra: convert to standard DMA DT bindings ASoC: tegra: allocate AHUB FIFO during probe() not startup() ASoC: tegra: call pm_runtime APIs around register accesses ASoC: tegra: use reset framework dma: tegra: register as an OF DMA controller dma: tegra: use reset framework ... Signed-off-by: Olof Johansson <[email protected]>
This commit is contained in:
commit
770039fef4
356 changed files with 8489 additions and 4794 deletions
|
|
@ -535,11 +535,41 @@ struct dma_chan *dma_get_slave_channel(struct dma_chan *chan)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(dma_get_slave_channel);
|
||||
|
||||
struct dma_chan *dma_get_any_slave_channel(struct dma_device *device)
|
||||
{
|
||||
dma_cap_mask_t mask;
|
||||
struct dma_chan *chan;
|
||||
int err;
|
||||
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
|
||||
/* lock against __dma_request_channel */
|
||||
mutex_lock(&dma_list_mutex);
|
||||
|
||||
chan = private_candidate(&mask, device, NULL, NULL);
|
||||
if (chan) {
|
||||
err = dma_chan_get(chan);
|
||||
if (err) {
|
||||
pr_debug("%s: failed to get %s: (%d)\n",
|
||||
__func__, dma_chan_name(chan), err);
|
||||
chan = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&dma_list_mutex);
|
||||
|
||||
return chan;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_get_any_slave_channel);
|
||||
|
||||
/**
|
||||
* __dma_request_channel - try to allocate an exclusive channel
|
||||
* @mask: capabilities that the channel must satisfy
|
||||
* @fn: optional callback to disposition available channels
|
||||
* @fn_param: opaque parameter to pass to dma_filter_fn
|
||||
*
|
||||
* Returns pointer to appropriate DMA channel on success or NULL.
|
||||
*/
|
||||
struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
|
||||
dma_filter_fn fn, void *fn_param)
|
||||
|
|
@ -591,18 +621,43 @@ EXPORT_SYMBOL_GPL(__dma_request_channel);
|
|||
* dma_request_slave_channel - try to allocate an exclusive slave channel
|
||||
* @dev: pointer to client device structure
|
||||
* @name: slave channel name
|
||||
*
|
||||
* Returns pointer to appropriate DMA channel on success or an error pointer.
|
||||
*/
|
||||
struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name)
|
||||
struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
|
||||
const char *name)
|
||||
{
|
||||
struct dma_chan *chan;
|
||||
|
||||
/* If device-tree is present get slave info from here */
|
||||
if (dev->of_node)
|
||||
return of_dma_request_slave_channel(dev->of_node, name);
|
||||
|
||||
/* If device was enumerated by ACPI get slave info from here */
|
||||
if (ACPI_HANDLE(dev))
|
||||
return acpi_dma_request_slave_chan_by_name(dev, name);
|
||||
if (ACPI_HANDLE(dev)) {
|
||||
chan = acpi_dma_request_slave_chan_by_name(dev, name);
|
||||
if (chan)
|
||||
return chan;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_request_slave_channel_reason);
|
||||
|
||||
/**
|
||||
* dma_request_slave_channel - try to allocate an exclusive slave channel
|
||||
* @dev: pointer to client device structure
|
||||
* @name: slave channel name
|
||||
*
|
||||
* Returns pointer to appropriate DMA channel on success or NULL.
|
||||
*/
|
||||
struct dma_chan *dma_request_slave_channel(struct device *dev,
|
||||
const char *name)
|
||||
{
|
||||
struct dma_chan *ch = dma_request_slave_channel_reason(dev, name);
|
||||
if (IS_ERR(ch))
|
||||
return NULL;
|
||||
return ch;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_request_slave_channel);
|
||||
|
||||
|
|
|
|||
|
|
@ -893,33 +893,17 @@ static struct dma_chan *mmp_pdma_dma_xlate(struct of_phandle_args *dma_spec,
|
|||
struct of_dma *ofdma)
|
||||
{
|
||||
struct mmp_pdma_device *d = ofdma->of_dma_data;
|
||||
struct dma_chan *chan, *candidate;
|
||||
struct dma_chan *chan;
|
||||
struct mmp_pdma_chan *c;
|
||||
|
||||
retry:
|
||||
candidate = NULL;
|
||||
|
||||
/* walk the list of channels registered with the current instance and
|
||||
* find one that is currently unused */
|
||||
list_for_each_entry(chan, &d->device.channels, device_node)
|
||||
if (chan->client_count == 0) {
|
||||
candidate = chan;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!candidate)
|
||||
chan = dma_get_any_slave_channel(&d->device);
|
||||
if (!chan)
|
||||
return NULL;
|
||||
|
||||
/* dma_get_slave_channel will return NULL if we lost a race between
|
||||
* the lookup and the reservation */
|
||||
chan = dma_get_slave_channel(candidate);
|
||||
c = to_mmp_pdma_chan(chan);
|
||||
c->drcmr = dma_spec->args[0];
|
||||
|
||||
if (chan) {
|
||||
struct mmp_pdma_chan *c = to_mmp_pdma_chan(chan);
|
||||
c->drcmr = dma_spec->args[0];
|
||||
return chan;
|
||||
}
|
||||
|
||||
goto retry;
|
||||
return chan;
|
||||
}
|
||||
|
||||
static int mmp_pdma_probe(struct platform_device *op)
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ static int of_dma_match_channel(struct device_node *np, const char *name,
|
|||
* @np: device node to get DMA request from
|
||||
* @name: name of desired channel
|
||||
*
|
||||
* Returns pointer to appropriate dma channel on success or NULL on error.
|
||||
* Returns pointer to appropriate DMA channel on success or an error pointer.
|
||||
*/
|
||||
struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
|
||||
const char *name)
|
||||
|
|
@ -152,17 +152,18 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
|
|||
struct of_dma *ofdma;
|
||||
struct dma_chan *chan;
|
||||
int count, i;
|
||||
int ret_no_channel = -ENODEV;
|
||||
|
||||
if (!np || !name) {
|
||||
pr_err("%s: not enough information provided\n", __func__);
|
||||
return NULL;
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
count = of_property_count_strings(np, "dma-names");
|
||||
if (count < 0) {
|
||||
pr_err("%s: dma-names property of node '%s' missing or empty\n",
|
||||
__func__, np->full_name);
|
||||
return NULL;
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
|
|
@ -172,10 +173,12 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
|
|||
mutex_lock(&of_dma_lock);
|
||||
ofdma = of_dma_find_controller(&dma_spec);
|
||||
|
||||
if (ofdma)
|
||||
if (ofdma) {
|
||||
chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
|
||||
else
|
||||
} else {
|
||||
ret_no_channel = -EPROBE_DEFER;
|
||||
chan = NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&of_dma_lock);
|
||||
|
||||
|
|
@ -185,7 +188,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
|
|||
return chan;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return ERR_PTR(ret_no_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* DMA driver for Nvidia's Tegra20 APB DMA controller.
|
||||
*
|
||||
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
|
|
@ -29,11 +29,12 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_dma.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
|
||||
#include "dmaengine.h"
|
||||
|
||||
|
|
@ -199,6 +200,7 @@ struct tegra_dma_channel {
|
|||
void *callback_param;
|
||||
|
||||
/* Channel-slave specific configuration */
|
||||
unsigned int slave_id;
|
||||
struct dma_slave_config dma_sconfig;
|
||||
struct tegra_dma_channel_regs channel_reg;
|
||||
};
|
||||
|
|
@ -208,6 +210,7 @@ struct tegra_dma {
|
|||
struct dma_device dma_dev;
|
||||
struct device *dev;
|
||||
struct clk *dma_clk;
|
||||
struct reset_control *rst;
|
||||
spinlock_t global_lock;
|
||||
void __iomem *base_addr;
|
||||
const struct tegra_dma_chip_data *chip_data;
|
||||
|
|
@ -339,6 +342,8 @@ static int tegra_dma_slave_config(struct dma_chan *dc,
|
|||
}
|
||||
|
||||
memcpy(&tdc->dma_sconfig, sconfig, sizeof(*sconfig));
|
||||
if (!tdc->slave_id)
|
||||
tdc->slave_id = sconfig->slave_id;
|
||||
tdc->config_init = true;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -941,7 +946,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
|
|||
ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32;
|
||||
|
||||
csr |= TEGRA_APBDMA_CSR_ONCE | TEGRA_APBDMA_CSR_FLOW;
|
||||
csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
|
||||
csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
|
||||
if (flags & DMA_PREP_INTERRUPT)
|
||||
csr |= TEGRA_APBDMA_CSR_IE_EOC;
|
||||
|
||||
|
|
@ -1085,7 +1090,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
|
|||
csr |= TEGRA_APBDMA_CSR_FLOW;
|
||||
if (flags & DMA_PREP_INTERRUPT)
|
||||
csr |= TEGRA_APBDMA_CSR_IE_EOC;
|
||||
csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
|
||||
csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
|
||||
|
||||
apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
|
||||
|
||||
|
|
@ -1205,6 +1210,25 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc)
|
|||
kfree(sg_req);
|
||||
}
|
||||
clk_disable_unprepare(tdma->dma_clk);
|
||||
|
||||
tdc->slave_id = 0;
|
||||
}
|
||||
|
||||
static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
struct of_dma *ofdma)
|
||||
{
|
||||
struct tegra_dma *tdma = ofdma->of_dma_data;
|
||||
struct dma_chan *chan;
|
||||
struct tegra_dma_channel *tdc;
|
||||
|
||||
chan = dma_get_any_slave_channel(&tdma->dma_dev);
|
||||
if (!chan)
|
||||
return NULL;
|
||||
|
||||
tdc = to_tegra_dma_chan(chan);
|
||||
tdc->slave_id = dma_spec->args[0];
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
/* Tegra20 specific DMA controller information */
|
||||
|
|
@ -1282,6 +1306,12 @@ static int tegra_dma_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(tdma->dma_clk);
|
||||
}
|
||||
|
||||
tdma->rst = devm_reset_control_get(&pdev->dev, "dma");
|
||||
if (IS_ERR(tdma->rst)) {
|
||||
dev_err(&pdev->dev, "Error: Missing reset\n");
|
||||
return PTR_ERR(tdma->rst);
|
||||
}
|
||||
|
||||
spin_lock_init(&tdma->global_lock);
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
|
@ -1302,9 +1332,9 @@ static int tegra_dma_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* Reset DMA controller */
|
||||
tegra_periph_reset_assert(tdma->dma_clk);
|
||||
reset_control_assert(tdma->rst);
|
||||
udelay(2);
|
||||
tegra_periph_reset_deassert(tdma->dma_clk);
|
||||
reset_control_deassert(tdma->rst);
|
||||
|
||||
/* Enable global DMA registers */
|
||||
tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE);
|
||||
|
|
@ -1376,10 +1406,20 @@ static int tegra_dma_probe(struct platform_device *pdev)
|
|||
goto err_irq;
|
||||
}
|
||||
|
||||
ret = of_dma_controller_register(pdev->dev.of_node,
|
||||
tegra_dma_of_xlate, tdma);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Tegra20 APB DMA OF registration failed %d\n", ret);
|
||||
goto err_unregister_dma_dev;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "Tegra20 APB DMA driver register %d channels\n",
|
||||
cdata->nr_channels);
|
||||
return 0;
|
||||
|
||||
err_unregister_dma_dev:
|
||||
dma_async_device_unregister(&tdma->dma_dev);
|
||||
err_irq:
|
||||
while (--i >= 0) {
|
||||
struct tegra_dma_channel *tdc = &tdma->channels[i];
|
||||
|
|
|
|||
Loading…
Reference in a new issue