dmaengine updates for 4.12-rc1

This time again a smaller update consisting of:
 
 - support for TI DA8xx dma controller and updates to the cppi driver
 - updates on bunch of drivers like xilinx, pl08x, stm32-dma, mv_xor, ioat,
   dmatest
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJZEebIAAoJEHwUBw8lI4NHZgYP/2t/pQiIuy0895tvljtpeqmO
 +g9waoxF9zWe2vO2R1HZAxT+Et7VGwYahE9+p+7uF8w8CyzT9sN6vASgq5xprlVI
 n2aZ2Ew8ZTFAoC+lT6Iy63/TFJNGP2gws2n6PrScptN9aQSSLgIn6AbunN1FRZi4
 TMuEROV3cLrPuF8qmStsQTqwW28FqQM8YJVZLy6Czak6siRSJDI++4Y1cOBOkGX6
 x44sFOuKxKvQW58SO1Dm491UAOh0SO9llB4W8BztGWDFPQtEZKSrBYJtV6ge2BaU
 UMxT/n1IbzPHYIRhRYitoc2BFKz6wf5ELH9N3qKSB76qbD9KogrEzwFK25CM8Po1
 nieHiFEfXDP8rnivxo3PV8ULzSZQ5Z2LGb+1BBqWhtfSlF69V63VWL5ER2kvxGoG
 klcSx2W2xrN4SpUuAh+koN/80ZE0OZpT+8EYmsJ8zfRg1y8ddn/8a82Q0lJZs979
 tbEunqJM0l/bqKDd3PQCEi2tTF0OpdZa6yU/twUSm1MVRNpsrpqoAgo7/mrYF5G4
 8rX/D5ihU1UijEYHKgMJHKCg4NFdYG/zqWABJQGbU6vLkOiuaDCzXIg7xZGCBx7R
 d2A7jYABPp2ljP1D5yTTfjxhN+UtIIiAl4DYz7OKc7dNaOhDz/ahl4oFIw4T7XfS
 Z4zjnDiDgSVZivS2HzaP
 =Ygkn
 -----END PGP SIGNATURE-----

Merge tag 'dmaengine-4.12-rc1' of git://git.infradead.org/users/vkoul/slave-dma

Pull dmaengine updates from Vinod Koul:
 "This time again a smaller update consisting of:

   - support for TI DA8xx dma controller and updates to the cppi driver

   - updates on bunch of drivers like xilinx, pl08x, stm32-dma, mv_xor,
     ioat, dmatest"

* tag 'dmaengine-4.12-rc1' of git://git.infradead.org/users/vkoul/slave-dma: (35 commits)
  dmaengine: pl08x: remove lock documentation
  dmaengine: pl08x: fix pl08x_dma_chan_state documentation
  dmaengine: pl08x: Use the BIT() macro consistently
  dmaengine: pl080: Fix some missing kerneldoc
  dmaengine: pl080: Cut some unused defines
  dmaengine: dmatest: Add check for supported buffer count (sg_buffers)
  dmaengine: dmatest: Select DMA_ENGINE_RAID as its needed for the slave_sg test
  dmaengine: virt-dma: Convert to use list_for_each_entry_safe()
  dma-debug: use offset_in_page() macro
  dmaengine: mv_xor: use offset_in_page() macro
  dmaengine: dmatest: use offset_in_page() macro
  dmaengine: sun4i: fix invalid argument
  dmaengine: ioat: use setup_timer
  dmaengine: cppi41: Fix an Oops happening in cppi41_dma_probe()
  dmaengine: pl330: remove pdata based initialization
  dmaengine: cppi: fix build error due to bad variable
  dmaengine: imx-sdma: add 1ms delay to ensure SDMA channel is stopped
  dmaengine: cppi41: use managed functions devm_*()
  dmaengine: cppi41: fix cppi41_dma_tx_status() logic
  dmaengine: qcom_hidma: pause the channel on shutdown
  ...
This commit is contained in:
Linus Torvalds 2017-05-09 15:40:28 -07:00
commit 4879b7ae05
20 changed files with 304 additions and 258 deletions

View File

@ -18,10 +18,26 @@ Required properties:
- phy-names: Should be "usb-phy"
- dmas: specifies the dma channels
- dma-names: specifies the names of the channels. Use "rxN" for receive
and "txN" for transmit endpoints. N specifies the endpoint number.
Optional properties:
~~~~~~~~~~~~~~~~~~~~
- vbus-supply: Phandle to a regulator providing the USB bus power.
DMA
~~~
- compatible: ti,da830-cppi41
- reg: offset and length of the following register spaces: CPPI DMA Controller,
CPPI DMA Scheduler, Queue Manager
- reg-names: "controller", "scheduler", "queuemgr"
- #dma-cells: should be set to 2. The first number represents the
channel number (0 … 3 for endpoints 1 … 4).
The second number is 0 for RX and 1 for TX transfers.
- #dma-channels: should be set to 4 representing the 4 endpoints.
Example:
usb_phy: usb-phy {
compatible = "ti,da830-usb-phy";
@ -30,7 +46,10 @@ Example:
};
usb0: usb@200000 {
compatible = "ti,da830-musb";
reg = <0x00200000 0x10000>;
reg = <0x00200000 0x1000>;
ranges;
#address-cells = <1>;
#size-cells = <1>;
interrupts = <58>;
interrupt-names = "mc";
@ -39,5 +58,25 @@ Example:
phys = <&usb_phy 0>;
phy-names = "usb-phy";
dmas = <&cppi41dma 0 0 &cppi41dma 1 0
&cppi41dma 2 0 &cppi41dma 3 0
&cppi41dma 0 1 &cppi41dma 1 1
&cppi41dma 2 1 &cppi41dma 3 1>;
dma-names =
"rx1", "rx2", "rx3", "rx4",
"tx1", "tx2", "tx3", "tx4";
status = "okay";
cppi41dma: dma-controller@201000 {
compatible = "ti,da830-cppi41";
reg = <0x201000 0x1000
0x202000 0x1000
0x204000 0x4000>;
reg-names = "controller", "scheduler", "queuemgr";
interrupts = <58>;
#dma-cells = <2>;
#dma-channels = <4>;
};
};

View File

@ -10,7 +10,6 @@
* published by the Free Software Foundation.
*/
#include <linux/amba/pl330.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>

View File

@ -514,12 +514,12 @@ config TIMB_DMA
Enable support for the Timberdale FPGA DMA engine.
config TI_CPPI41
tristate "AM33xx CPPI41 DMA support"
depends on ARCH_OMAP
tristate "CPPI 4.1 DMA support"
depends on (ARCH_OMAP || ARCH_DAVINCI_DA8XX)
select DMA_ENGINE
help
The Communications Port Programming Interface (CPPI) 4.1 DMA engine
is currently used by the USB driver on AM335x platforms.
is currently used by the USB driver on AM335x and DA8xx platforms.
config TI_DMA_CROSSBAR
bool
@ -608,6 +608,7 @@ config ASYNC_TX_DMA
config DMATEST
tristate "DMA Test client"
depends on DMA_ENGINE
select DMA_ENGINE_RAID
help
Simple DMA test client. Say N unless you're debugging a
DMA Device driver.

View File

@ -106,6 +106,7 @@ struct pl08x_driver_data;
/**
* struct vendor_data - vendor-specific config parameters for PL08x derivatives
* @config_offset: offset to the configuration register
* @channels: the number of channels available in this variant
* @signals: the number of request signals available from the hardware
* @dualmaster: whether this version supports dual AHB masters or not.
@ -145,6 +146,8 @@ struct pl08x_bus_data {
/**
* struct pl08x_phy_chan - holder for the physical channels
* @id: physical index to this channel
* @base: memory base address for this physical channel
* @reg_config: configuration address for this physical channel
* @lock: a lock to use when altering an instance of this struct
* @serving: the virtual channel currently being served by this physical
* channel
@ -203,7 +206,7 @@ struct pl08x_txd {
};
/**
* struct pl08x_dma_chan_state - holds the PL08x specific virtual channel
* enum pl08x_dma_chan_state - holds the PL08x specific virtual channel
* states
* @PL08X_CHAN_IDLE: the channel is idle
* @PL08X_CHAN_RUNNING: the channel has allocated a physical transport
@ -226,9 +229,8 @@ enum pl08x_dma_chan_state {
* @phychan: the physical channel utilized by this channel, if there is one
* @name: name of channel
* @cd: channel platform data
* @runtime_addr: address for RX/TX according to the runtime config
* @cfg: slave configuration
* @at: active transaction on this channel
* @lock: a lock for this channel data
* @host: a pointer to the host (internal use)
* @state: whether the channel is idle, paused, running etc
* @slave: whether this channel is a device (slave) or for memcpy
@ -262,7 +264,7 @@ struct pl08x_dma_chan {
* @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI
* fetches
* @mem_buses: set to indicate memory transfers on AHB2.
* @lock: a spinlock for this struct
* @lli_words: how many words are used in each LLI item for this variant
*/
struct pl08x_driver_data {
struct dma_device slave;
@ -417,7 +419,7 @@ static void pl08x_start_next_txd(struct pl08x_dma_chan *plchan)
/* Enable the DMA channel */
/* Do not access config register until channel shows as disabled */
while (readl(pl08x->base + PL080_EN_CHAN) & (1 << phychan->id))
while (readl(pl08x->base + PL080_EN_CHAN) & BIT(phychan->id))
cpu_relax();
/* Do not access config register until channel shows as inactive */
@ -484,8 +486,8 @@ static void pl08x_terminate_phy_chan(struct pl08x_driver_data *pl08x,
writel(val, ch->reg_config);
writel(1 << ch->id, pl08x->base + PL080_ERR_CLEAR);
writel(1 << ch->id, pl08x->base + PL080_TC_CLEAR);
writel(BIT(ch->id), pl08x->base + PL080_ERR_CLEAR);
writel(BIT(ch->id), pl08x->base + PL080_TC_CLEAR);
}
static inline u32 get_bytes_in_cctl(u32 cctl)
@ -1834,7 +1836,7 @@ static irqreturn_t pl08x_irq(int irq, void *dev)
return IRQ_NONE;
for (i = 0; i < pl08x->vd->channels; i++) {
if (((1 << i) & err) || ((1 << i) & tc)) {
if ((BIT(i) & err) || (BIT(i) & tc)) {
/* Locate physical channel */
struct pl08x_phy_chan *phychan = &pl08x->phy_chans[i];
struct pl08x_dma_chan *plchan = phychan->serving;
@ -1872,7 +1874,7 @@ static irqreturn_t pl08x_irq(int irq, void *dev)
}
spin_unlock(&plchan->vc.lock);
mask |= (1 << i);
mask |= BIT(i);
}
}

View File

@ -68,7 +68,6 @@
#define QMGR_MEMCTRL_IDX_SH 16
#define QMGR_MEMCTRL_DESC_SH 8
#define QMGR_NUM_PEND 5
#define QMGR_PEND(x) (0x90 + (x) * 4)
#define QMGR_PENDING_SLOT_Q(x) (x / 32)
@ -131,7 +130,6 @@ struct cppi41_dd {
u32 first_td_desc;
struct cppi41_channel *chan_busy[ALLOC_DECS_NUM];
void __iomem *usbss_mem;
void __iomem *ctrl_mem;
void __iomem *sched_mem;
void __iomem *qmgr_mem;
@ -139,6 +137,10 @@ struct cppi41_dd {
const struct chan_queues *queues_rx;
const struct chan_queues *queues_tx;
struct chan_queues td_queue;
u16 first_completion_queue;
u16 qmgr_num_pend;
u32 n_chans;
u8 platform;
struct list_head pending; /* Pending queued transfers */
spinlock_t lock; /* Lock for pending list */
@ -149,8 +151,7 @@ struct cppi41_dd {
bool is_suspended;
};
#define FIST_COMPLETION_QUEUE 93
static struct chan_queues usb_queues_tx[] = {
static struct chan_queues am335x_usb_queues_tx[] = {
/* USB0 ENDP 1 */
[ 0] = { .submit = 32, .complete = 93},
[ 1] = { .submit = 34, .complete = 94},
@ -186,7 +187,7 @@ static struct chan_queues usb_queues_tx[] = {
[29] = { .submit = 90, .complete = 139},
};
static const struct chan_queues usb_queues_rx[] = {
static const struct chan_queues am335x_usb_queues_rx[] = {
/* USB0 ENDP 1 */
[ 0] = { .submit = 1, .complete = 109},
[ 1] = { .submit = 2, .complete = 110},
@ -222,11 +223,26 @@ static const struct chan_queues usb_queues_rx[] = {
[29] = { .submit = 30, .complete = 155},
};
static const struct chan_queues da8xx_usb_queues_tx[] = {
[0] = { .submit = 16, .complete = 24},
[1] = { .submit = 18, .complete = 24},
[2] = { .submit = 20, .complete = 24},
[3] = { .submit = 22, .complete = 24},
};
static const struct chan_queues da8xx_usb_queues_rx[] = {
[0] = { .submit = 1, .complete = 26},
[1] = { .submit = 3, .complete = 26},
[2] = { .submit = 5, .complete = 26},
[3] = { .submit = 7, .complete = 26},
};
struct cppi_glue_infos {
irqreturn_t (*isr)(int irq, void *data);
const struct chan_queues *queues_rx;
const struct chan_queues *queues_tx;
struct chan_queues td_queue;
u16 first_completion_queue;
u16 qmgr_num_pend;
};
static struct cppi41_channel *to_cpp41_chan(struct dma_chan *c)
@ -285,19 +301,21 @@ static u32 cppi41_pop_desc(struct cppi41_dd *cdd, unsigned queue_num)
static irqreturn_t cppi41_irq(int irq, void *data)
{
struct cppi41_dd *cdd = data;
u16 first_completion_queue = cdd->first_completion_queue;
u16 qmgr_num_pend = cdd->qmgr_num_pend;
struct cppi41_channel *c;
int i;
for (i = QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE); i < QMGR_NUM_PEND;
for (i = QMGR_PENDING_SLOT_Q(first_completion_queue); i < qmgr_num_pend;
i++) {
u32 val;
u32 q_num;
val = cppi_readl(cdd->qmgr_mem + QMGR_PEND(i));
if (i == QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE) && val) {
if (i == QMGR_PENDING_SLOT_Q(first_completion_queue) && val) {
u32 mask;
/* set corresponding bit for completetion Q 93 */
mask = 1 << QMGR_PENDING_BIT_Q(FIST_COMPLETION_QUEUE);
mask = 1 << QMGR_PENDING_BIT_Q(first_completion_queue);
/* not set all bits for queues less than Q 93 */
mask--;
/* now invert and keep only Q 93+ set */
@ -402,11 +420,9 @@ static enum dma_status cppi41_dma_tx_status(struct dma_chan *chan,
struct cppi41_channel *c = to_cpp41_chan(chan);
enum dma_status ret;
/* lock */
ret = dma_cookie_status(chan, cookie, txstate);
if (txstate && ret == DMA_COMPLETE)
txstate->residue = c->residue;
/* unlock */
dma_set_residue(txstate, c->residue);
return ret;
}
@ -630,7 +646,7 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c)
if (!c->is_tx) {
reg |= GCR_STARV_RETRY;
reg |= GCR_DESC_TYPE_HOST;
reg |= c->q_comp_num;
reg |= cdd->td_queue.complete;
}
reg |= GCR_TEARDOWN;
cppi_writel(reg, c->gcr_reg);
@ -641,7 +657,7 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c)
if (!c->td_seen || !c->td_desc_seen) {
desc_phys = cppi41_pop_desc(cdd, cdd->td_queue.complete);
if (!desc_phys)
if (!desc_phys && c->is_tx)
desc_phys = cppi41_pop_desc(cdd, c->q_comp_num);
if (desc_phys == c->desc_phys) {
@ -723,39 +739,24 @@ static int cppi41_stop_chan(struct dma_chan *chan)
return 0;
}
static void cleanup_chans(struct cppi41_dd *cdd)
{
while (!list_empty(&cdd->ddev.channels)) {
struct cppi41_channel *cchan;
cchan = list_first_entry(&cdd->ddev.channels,
struct cppi41_channel, chan.device_node);
list_del(&cchan->chan.device_node);
kfree(cchan);
}
}
static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd)
{
struct cppi41_channel *cchan;
struct cppi41_channel *cchan, *chans;
int i;
int ret;
u32 n_chans;
u32 n_chans = cdd->n_chans;
ret = of_property_read_u32(dev->of_node, "#dma-channels",
&n_chans);
if (ret)
return ret;
/*
* The channels can only be used as TX or as RX. So we add twice
* that much dma channels because USB can only do RX or TX.
*/
n_chans *= 2;
chans = devm_kcalloc(dev, n_chans, sizeof(*chans), GFP_KERNEL);
if (!chans)
return -ENOMEM;
for (i = 0; i < n_chans; i++) {
cchan = kzalloc(sizeof(*cchan), GFP_KERNEL);
if (!cchan)
goto err;
cchan = &chans[i];
cchan->cdd = cdd;
if (i & 1) {
@ -775,9 +776,6 @@ static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd)
cdd->first_td_desc = n_chans;
return 0;
err:
cleanup_chans(cdd);
return -ENOMEM;
}
static void purge_descs(struct device *dev, struct cppi41_dd *cdd)
@ -859,7 +857,7 @@ static void init_sched(struct cppi41_dd *cdd)
word = 0;
cppi_writel(0, cdd->sched_mem + DMA_SCHED_CTRL);
for (ch = 0; ch < 15 * 2; ch += 2) {
for (ch = 0; ch < cdd->n_chans; ch += 2) {
reg = SCHED_ENTRY0_CHAN(ch);
reg |= SCHED_ENTRY1_CHAN(ch) | SCHED_ENTRY1_IS_RX;
@ -869,7 +867,7 @@ static void init_sched(struct cppi41_dd *cdd)
cppi_writel(reg, cdd->sched_mem + DMA_SCHED_WORD(word));
word++;
}
reg = 15 * 2 * 2 - 1;
reg = cdd->n_chans * 2 - 1;
reg |= DMA_SCHED_CTRL_EN;
cppi_writel(reg, cdd->sched_mem + DMA_SCHED_CTRL);
}
@ -885,7 +883,7 @@ static int init_cppi41(struct device *dev, struct cppi41_dd *cdd)
return -ENOMEM;
cppi_writel(cdd->scratch_phys, cdd->qmgr_mem + QMGR_LRAM0_BASE);
cppi_writel(QMGR_SCRATCH_SIZE, cdd->qmgr_mem + QMGR_LRAM_SIZE);
cppi_writel(TOTAL_DESCS_NUM, cdd->qmgr_mem + QMGR_LRAM_SIZE);
cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE);
ret = init_descs(dev, cdd);
@ -894,6 +892,7 @@ static int init_cppi41(struct device *dev, struct cppi41_dd *cdd)
cppi_writel(cdd->td_queue.submit, cdd->ctrl_mem + DMA_TDFDQ);
init_sched(cdd);
return 0;
err_td:
deinit_cppi41(dev, cdd);
@ -933,8 +932,9 @@ static bool cpp41_dma_filter_fn(struct dma_chan *chan, void *param)
else
queues = cdd->queues_rx;
BUILD_BUG_ON(ARRAY_SIZE(usb_queues_rx) != ARRAY_SIZE(usb_queues_tx));
if (WARN_ON(cchan->port_num > ARRAY_SIZE(usb_queues_rx)))
BUILD_BUG_ON(ARRAY_SIZE(am335x_usb_queues_rx) !=
ARRAY_SIZE(am335x_usb_queues_tx));
if (WARN_ON(cchan->port_num > ARRAY_SIZE(am335x_usb_queues_rx)))
return false;
cchan->q_num = queues[cchan->port_num].submit;
@ -962,15 +962,25 @@ static struct dma_chan *cppi41_dma_xlate(struct of_phandle_args *dma_spec,
&dma_spec->args[0]);
}
static const struct cppi_glue_infos usb_infos = {
.isr = cppi41_irq,
.queues_rx = usb_queues_rx,
.queues_tx = usb_queues_tx,
static const struct cppi_glue_infos am335x_usb_infos = {
.queues_rx = am335x_usb_queues_rx,
.queues_tx = am335x_usb_queues_tx,
.td_queue = { .submit = 31, .complete = 0 },
.first_completion_queue = 93,
.qmgr_num_pend = 5,
};
static const struct cppi_glue_infos da8xx_usb_infos = {
.queues_rx = da8xx_usb_queues_rx,
.queues_tx = da8xx_usb_queues_tx,
.td_queue = { .submit = 31, .complete = 0 },
.first_completion_queue = 24,
.qmgr_num_pend = 2,
};
static const struct of_device_id cppi41_dma_ids[] = {
{ .compatible = "ti,am3359-cppi41", .data = &usb_infos},
{ .compatible = "ti,am3359-cppi41", .data = &am335x_usb_infos},
{ .compatible = "ti,da830-cppi41", .data = &da8xx_usb_infos},
{},
};
MODULE_DEVICE_TABLE(of, cppi41_dma_ids);
@ -995,6 +1005,8 @@ static int cppi41_dma_probe(struct platform_device *pdev)
struct cppi41_dd *cdd;
struct device *dev = &pdev->dev;
const struct cppi_glue_infos *glue_info;
struct resource *mem;
int index;
int irq;
int ret;
@ -1021,19 +1033,31 @@ static int cppi41_dma_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&cdd->ddev.channels);
cpp41_dma_info.dma_cap = cdd->ddev.cap_mask;
cdd->usbss_mem = of_iomap(dev->of_node, 0);
cdd->ctrl_mem = of_iomap(dev->of_node, 1);
cdd->sched_mem = of_iomap(dev->of_node, 2);
cdd->qmgr_mem = of_iomap(dev->of_node, 3);
index = of_property_match_string(dev->of_node,
"reg-names", "controller");
if (index < 0)
return index;
mem = platform_get_resource(pdev, IORESOURCE_MEM, index);
cdd->ctrl_mem = devm_ioremap_resource(dev, mem);
if (IS_ERR(cdd->ctrl_mem))
return PTR_ERR(cdd->ctrl_mem);
mem = platform_get_resource(pdev, IORESOURCE_MEM, index + 1);
cdd->sched_mem = devm_ioremap_resource(dev, mem);
if (IS_ERR(cdd->sched_mem))
return PTR_ERR(cdd->sched_mem);
mem = platform_get_resource(pdev, IORESOURCE_MEM, index + 2);
cdd->qmgr_mem = devm_ioremap_resource(dev, mem);
if (IS_ERR(cdd->qmgr_mem))
return PTR_ERR(cdd->qmgr_mem);
spin_lock_init(&cdd->lock);
INIT_LIST_HEAD(&cdd->pending);
platform_set_drvdata(pdev, cdd);
if (!cdd->usbss_mem || !cdd->ctrl_mem || !cdd->sched_mem ||
!cdd->qmgr_mem)
return -ENXIO;
pm_runtime_enable(dev);
pm_runtime_set_autosuspend_delay(dev, 100);
pm_runtime_use_autosuspend(dev);
@ -1044,6 +1068,13 @@ static int cppi41_dma_probe(struct platform_device *pdev)
cdd->queues_rx = glue_info->queues_rx;
cdd->queues_tx = glue_info->queues_tx;
cdd->td_queue = glue_info->td_queue;
cdd->qmgr_num_pend = glue_info->qmgr_num_pend;
cdd->first_completion_queue = glue_info->first_completion_queue;
ret = of_property_read_u32(dev->of_node,
"#dma-channels", &cdd->n_chans);
if (ret)
goto err_get_n_chans;
ret = init_cppi41(dev, cdd);
if (ret)
@ -1056,18 +1087,18 @@ static int cppi41_dma_probe(struct platform_device *pdev)
irq = irq_of_parse_and_map(dev->of_node, 0);
if (!irq) {
ret = -EINVAL;
goto err_irq;
goto err_chans;
}
ret = devm_request_irq(&pdev->dev, irq, glue_info->isr, IRQF_SHARED,
ret = devm_request_irq(&pdev->dev, irq, cppi41_irq, IRQF_SHARED,
dev_name(dev), cdd);
if (ret)
goto err_irq;
goto err_chans;
cdd->irq = irq;
ret = dma_async_device_register(&cdd->ddev);
if (ret)
goto err_dma_reg;
goto err_chans;
ret = of_dma_controller_register(dev->of_node,
cppi41_dma_xlate, &cpp41_dma_info);
@ -1080,20 +1111,14 @@ static int cppi41_dma_probe(struct platform_device *pdev)
return 0;
err_of:
dma_async_device_unregister(&cdd->ddev);
err_dma_reg:
err_irq:
cleanup_chans(cdd);
err_chans:
deinit_cppi41(dev, cdd);
err_init_cppi:
pm_runtime_dont_use_autosuspend(dev);
err_get_n_chans:
err_get_sync:
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
iounmap(cdd->usbss_mem);
iounmap(cdd->ctrl_mem);
iounmap(cdd->sched_mem);
iounmap(cdd->qmgr_mem);
return ret;
}
@ -1110,12 +1135,7 @@ static int cppi41_dma_remove(struct platform_device *pdev)
dma_async_device_unregister(&cdd->ddev);
devm_free_irq(&pdev->dev, cdd->irq, cdd);
cleanup_chans(cdd);
deinit_cppi41(&pdev->dev, cdd);
iounmap(cdd->usbss_mem);
iounmap(cdd->ctrl_mem);
iounmap(cdd->sched_mem);
iounmap(cdd->qmgr_mem);
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);

View File

@ -535,6 +535,13 @@ static int dmatest_func(void *data)
total_tests++;
/* Check if buffer count fits into map count variable (u8) */
if ((src_cnt + dst_cnt) >= 255) {
pr_err("too many buffers (%d of 255 supported)\n",
src_cnt + dst_cnt);
break;
}
if (1 << align > params->buf_size) {
pr_err("%u-byte buffer too small for %d-byte alignment\n",
params->buf_size, 1 << align);
@ -585,7 +592,7 @@ static int dmatest_func(void *data)
for (i = 0; i < src_cnt; i++) {
void *buf = thread->srcs[i];
struct page *pg = virt_to_page(buf);
unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
unsigned long pg_off = offset_in_page(buf);
um->addr[i] = dma_map_page(dev->dev, pg, pg_off,
um->len, DMA_TO_DEVICE);
@ -605,7 +612,7 @@ static int dmatest_func(void *data)
for (i = 0; i < dst_cnt; i++) {
void *buf = thread->dsts[i];
struct page *pg = virt_to_page(buf);
unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
unsigned long pg_off = offset_in_page(buf);
dsts[i] = dma_map_page(dev->dev, pg, pg_off, um->len,
DMA_BIDIRECTIONAL);

View File

@ -937,6 +937,21 @@ static int sdma_disable_channel(struct dma_chan *chan)
return 0;
}
static int sdma_disable_channel_with_delay(struct dma_chan *chan)
{
sdma_disable_channel(chan);
/*
* According to NXP R&D team a delay of one BD SDMA cost time
* (maximum is 1ms) should be added after disable of the channel
* bit, to ensure SDMA core has really been stopped after SDMA
* clients call .device_terminate_all.
*/
mdelay(1);
return 0;
}
static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac)
{
struct sdma_engine *sdma = sdmac->sdma;
@ -1828,11 +1843,11 @@ static int sdma_probe(struct platform_device *pdev)
sdma->dma_device.device_prep_slave_sg = sdma_prep_slave_sg;
sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic;
sdma->dma_device.device_config = sdma_config;
sdma->dma_device.device_terminate_all = sdma_disable_channel;
sdma->dma_device.device_terminate_all = sdma_disable_channel_with_delay;
sdma->dma_device.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
sdma->dma_device.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
sdma->dma_device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
sdma->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
sdma->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
sdma->dma_device.device_issue_pending = sdma_issue_pending;
sdma->dma_device.dev->dma_parms = &sdma->dma_parms;
dma_set_max_seg_size(sdma->dma_device.dev, 65535);

View File

@ -760,9 +760,7 @@ ioat_init_channel(struct ioatdma_device *ioat_dma,
dma_cookie_init(&ioat_chan->dma_chan);
list_add_tail(&ioat_chan->dma_chan.device_node, &dma->channels);
ioat_dma->idx[idx] = ioat_chan;
init_timer(&ioat_chan->timer);
ioat_chan->timer.function = ioat_timer_event;
ioat_chan->timer.data = data;
setup_timer(&ioat_chan->timer, ioat_timer_event, data);
tasklet_init(&ioat_chan->cleanup_task, ioat_cleanup_event, data);
}

View File

@ -960,7 +960,7 @@ static int mv_chan_memcpy_self_test(struct mv_xor_chan *mv_chan)
}
src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src),
(size_t)src & ~PAGE_MASK, PAGE_SIZE,
offset_in_page(src), PAGE_SIZE,
DMA_TO_DEVICE);
unmap->addr[0] = src_dma;
@ -972,7 +972,7 @@ static int mv_chan_memcpy_self_test(struct mv_xor_chan *mv_chan)
unmap->to_cnt = 1;
dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest),
(size_t)dest & ~PAGE_MASK, PAGE_SIZE,
offset_in_page(dest), PAGE_SIZE,
DMA_FROM_DEVICE);
unmap->addr[1] = dest_dma;
@ -1580,11 +1580,6 @@ static int mv_xor_probe(struct platform_device *pdev)
int irq;
cd = &pdata->channels[i];
if (!cd) {
ret = -ENODEV;
goto err_channel_add;
}
irq = platform_get_irq(pdev, i);
if (irq < 0) {
ret = irq;

View File

@ -22,7 +22,6 @@
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/amba/bus.h>
#include <linux/amba/pl330.h>
#include <linux/scatterlist.h>
#include <linux/of.h>
#include <linux/of_dma.h>
@ -2077,18 +2076,6 @@ static void pl330_tasklet(unsigned long data)
}
}
bool pl330_filter(struct dma_chan *chan, void *param)
{
u8 *peri_id;
if (chan->device->dev->driver != &pl330_driver.drv)
return false;
peri_id = chan->private;
return *peri_id == (unsigned long)param;
}
EXPORT_SYMBOL(pl330_filter);
static struct dma_chan *of_dma_pl330_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma)
{
@ -2833,7 +2820,6 @@ static SIMPLE_DEV_PM_OPS(pl330_pm, pl330_suspend, pl330_resume);
static int
pl330_probe(struct amba_device *adev, const struct amba_id *id)
{
struct dma_pl330_platdata *pdat;
struct pl330_config *pcfg;
struct pl330_dmac *pl330;
struct dma_pl330_chan *pch, *_p;
@ -2843,8 +2829,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
int num_chan;
struct device_node *np = adev->dev.of_node;
pdat = dev_get_platdata(&adev->dev);
ret = dma_set_mask_and_coherent(&adev->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
@ -2857,7 +2841,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
pd = &pl330->ddma;
pd->dev = &adev->dev;
pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
pl330->mcbufsz = 0;
/* get quirk */
for (i = 0; i < ARRAY_SIZE(of_quirks); i++)
@ -2901,9 +2885,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
INIT_LIST_HEAD(&pd->channels);
/* Initialize channel parameters */
if (pdat)
num_chan = max_t(int, pdat->nr_valid_peri, pcfg->num_chan);
else
num_chan = max_t(int, pcfg->num_peri, pcfg->num_chan);
pl330->num_peripherals = num_chan;
@ -2916,11 +2897,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
for (i = 0; i < num_chan; i++) {
pch = &pl330->peripherals[i];
if (!adev->dev.of_node)
pch->chan.private = pdat ? &pdat->peri_id[i] : NULL;
else
pch->chan.private = adev->dev.of_node;
pch->chan.private = adev->dev.of_node;
INIT_LIST_HEAD(&pch->submitted_list);
INIT_LIST_HEAD(&pch->work_list);
INIT_LIST_HEAD(&pch->completed_list);
@ -2933,16 +2911,12 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
list_add_tail(&pch->chan.device_node, &pd->channels);
}
if (pdat) {
pd->cap_mask = pdat->cap_mask;
} else {
dma_cap_set(DMA_MEMCPY, pd->cap_mask);
if (pcfg->num_peri) {
dma_cap_set(DMA_SLAVE, pd->cap_mask);
dma_cap_set(DMA_CYCLIC, pd->cap_mask);
dma_cap_set(DMA_PRIVATE, pd->cap_mask);
}
}
pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
pd->device_free_chan_resources = pl330_free_chan_resources;

View File

@ -865,6 +865,20 @@ static int hidma_probe(struct platform_device *pdev)
return rc;
}
static void hidma_shutdown(struct platform_device *pdev)
{
struct hidma_dev *dmadev = platform_get_drvdata(pdev);
dev_info(dmadev->ddev.dev, "HI-DMA engine shutdown\n");
pm_runtime_get_sync(dmadev->ddev.dev);
if (hidma_ll_disable(dmadev->lldev))
dev_warn(dmadev->ddev.dev, "channel did not stop\n");
pm_runtime_mark_last_busy(dmadev->ddev.dev);
pm_runtime_put_autosuspend(dmadev->ddev.dev);
}
static int hidma_remove(struct platform_device *pdev)
{
struct hidma_dev *dmadev = platform_get_drvdata(pdev);
@ -908,6 +922,7 @@ MODULE_DEVICE_TABLE(of, hidma_match);
static struct platform_driver hidma_driver = {
.probe = hidma_probe,
.remove = hidma_remove,
.shutdown = hidma_shutdown,
.driver = {
.name = "hidma",
.of_match_table = hidma_match,

View File

@ -499,6 +499,9 @@ int hidma_ll_enable(struct hidma_lldev *lldev)
lldev->trch_state = HIDMA_CH_ENABLED;
lldev->evch_state = HIDMA_CH_ENABLED;
/* enable irqs */
writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
return 0;
}
@ -596,6 +599,9 @@ int hidma_ll_disable(struct hidma_lldev *lldev)
lldev->trch_state = HIDMA_CH_SUSPENDED;
lldev->evch_state = HIDMA_CH_SUSPENDED;
/* disable interrupts */
writel(0, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
return 0;
}

View File

@ -344,13 +344,19 @@ static void rcar_dmac_chan_start_xfer(struct rcar_dmac_chan *chan)
rcar_dmac_chan_write(chan, RCAR_DMARS, chan->mid_rid);
if (desc->hwdescs.use) {
struct rcar_dmac_xfer_chunk *chunk;
struct rcar_dmac_xfer_chunk *chunk =
list_first_entry(&desc->chunks,
struct rcar_dmac_xfer_chunk, node);
dev_dbg(chan->chan.device->dev,
"chan%u: queue desc %p: %u@%pad\n",
chan->index, desc, desc->nchunks, &desc->hwdescs.dma);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
rcar_dmac_chan_write(chan, RCAR_DMAFIXSAR,
chunk->src_addr >> 32);
rcar_dmac_chan_write(chan, RCAR_DMAFIXDAR,
chunk->dst_addr >> 32);
rcar_dmac_chan_write(chan, RCAR_DMAFIXDPBASE,
desc->hwdescs.dma >> 32);
#endif
@ -368,8 +374,6 @@ static void rcar_dmac_chan_start_xfer(struct rcar_dmac_chan *chan)
* should. Initialize it manually with the destination address
* of the first chunk.
*/
chunk = list_first_entry(&desc->chunks,
struct rcar_dmac_xfer_chunk, node);
rcar_dmac_chan_write(chan, RCAR_DMADAR,
chunk->dst_addr & 0xffffffff);
@ -855,8 +859,12 @@ rcar_dmac_chan_prep_sg(struct rcar_dmac_chan *chan, struct scatterlist *sgl,
unsigned int nchunks = 0;
unsigned int max_chunk_size;
unsigned int full_size = 0;
bool highmem = false;
bool cross_boundary = false;
unsigned int i;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
u32 high_dev_addr;
u32 high_mem_addr;
#endif
desc = rcar_dmac_desc_get(chan);
if (!desc)
@ -882,6 +890,16 @@ rcar_dmac_chan_prep_sg(struct rcar_dmac_chan *chan, struct scatterlist *sgl,
full_size += len;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
if (i == 0) {
high_dev_addr = dev_addr >> 32;
high_mem_addr = mem_addr >> 32;
}
if ((dev_addr >> 32 != high_dev_addr) ||
(mem_addr >> 32 != high_mem_addr))
cross_boundary = true;
#endif
while (len) {
unsigned int size = min(len, max_chunk_size);
@ -890,18 +908,14 @@ rcar_dmac_chan_prep_sg(struct rcar_dmac_chan *chan, struct scatterlist *sgl,
* Prevent individual transfers from crossing 4GB
* boundaries.
*/
if (dev_addr >> 32 != (dev_addr + size - 1) >> 32)
if (dev_addr >> 32 != (dev_addr + size - 1) >> 32) {
size = ALIGN(dev_addr, 1ULL << 32) - dev_addr;
if (mem_addr >> 32 != (mem_addr + size - 1) >> 32)
cross_boundary = true;
}
if (mem_addr >> 32 != (mem_addr + size - 1) >> 32) {
size = ALIGN(mem_addr, 1ULL << 32) - mem_addr;
/*
* Check if either of the source or destination address
* can't be expressed in 32 bits. If so we can't use
* hardware descriptor lists.
*/
if (dev_addr >> 32 || mem_addr >> 32)
highmem = true;
cross_boundary = true;
}
#endif
chunk = rcar_dmac_xfer_chunk_get(chan);
@ -943,13 +957,11 @@ rcar_dmac_chan_prep_sg(struct rcar_dmac_chan *chan, struct scatterlist *sgl,
* Use hardware descriptor lists if possible when more than one chunk
* needs to be transferred (otherwise they don't make much sense).
*
* The highmem check currently covers the whole transfer. As an
* optimization we could use descriptor lists for consecutive lowmem
* chunks and direct manual mode for highmem chunks. Whether the
* performance improvement would be significant enough compared to the
* additional complexity remains to be investigated.
* Source/Destination address should be located in same 4GiB region
* in the 40bit address space when it uses Hardware descriptor,
* and cross_boundary is checking it.
*/
desc->hwdescs.use = !highmem && nchunks > 1;
desc->hwdescs.use = !cross_boundary && nchunks > 1;
if (desc->hwdescs.use) {
if (rcar_dmac_fill_hwdesc(chan, desc) < 0)
desc->hwdescs.use = false;

View File

@ -1008,7 +1008,7 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
c = dma_get_slave_channel(&chan->vchan.chan);
if (!c) {
dev_err(dev, "No more channel avalaible\n");
dev_err(dev, "No more channels available\n");
return NULL;
}

View File

@ -238,7 +238,7 @@ static struct sun4i_dma_pchan *find_and_use_pchan(struct sun4i_dma_dev *priv,
}
spin_lock_irqsave(&priv->lock, flags);
for_each_clear_bit_from(i, &priv->pchans_used, max) {
for_each_clear_bit_from(i, priv->pchans_used, max) {
pchan = &pchans[i];
pchan->vchan = vchan;
set_bit(i, priv->pchans_used);

View File

@ -86,7 +86,7 @@ EXPORT_SYMBOL_GPL(vchan_find_desc);
static void vchan_complete(unsigned long arg)
{
struct virt_dma_chan *vc = (struct virt_dma_chan *)arg;
struct virt_dma_desc *vd;
struct virt_dma_desc *vd, *_vd;
struct dmaengine_desc_callback cb;
LIST_HEAD(head);
@ -103,8 +103,7 @@ static void vchan_complete(unsigned long arg)
dmaengine_desc_callback_invoke(&cb, NULL);
while (!list_empty(&head)) {
vd = list_first_entry(&head, struct virt_dma_desc, node);
list_for_each_entry_safe(vd, _vd, &head, node) {
dmaengine_desc_get_callback(&vd->tx, &cb);
list_del(&vd->node);
@ -119,9 +118,9 @@ static void vchan_complete(unsigned long arg)
void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head)
{
while (!list_empty(head)) {
struct virt_dma_desc *vd = list_first_entry(head,
struct virt_dma_desc, node);
struct virt_dma_desc *vd, *_vd;
list_for_each_entry_safe(vd, _vd, head, node) {
if (dmaengine_desc_test_reuse(&vd->tx)) {
list_move_tail(&vd->node, &vc->desc_allocated);
} else {

View File

@ -331,6 +331,7 @@ struct xilinx_dma_tx_descriptor {
* @seg_v: Statically allocated segments base
* @cyclic_seg_v: Statically allocated segment base for cyclic transfers
* @start_transfer: Differentiate b/w DMA IP's transfer
* @stop_transfer: Differentiate b/w DMA IP's quiesce
*/
struct xilinx_dma_chan {
struct xilinx_dma_device *xdev;
@ -361,6 +362,7 @@ struct xilinx_dma_chan {
struct xilinx_axidma_tx_segment *seg_v;
struct xilinx_axidma_tx_segment *cyclic_seg_v;
void (*start_transfer)(struct xilinx_dma_chan *chan);
int (*stop_transfer)(struct xilinx_dma_chan *chan);
u16 tdest;
};
@ -946,26 +948,32 @@ static bool xilinx_dma_is_idle(struct xilinx_dma_chan *chan)
}
/**
* xilinx_dma_halt - Halt DMA channel
* xilinx_dma_stop_transfer - Halt DMA channel
* @chan: Driver specific DMA channel
*/
static void xilinx_dma_halt(struct xilinx_dma_chan *chan)
static int xilinx_dma_stop_transfer(struct xilinx_dma_chan *chan)
{
int err;
u32 val;
dma_ctrl_clr(chan, XILINX_DMA_REG_DMACR, XILINX_DMA_DMACR_RUNSTOP);
/* Wait for the hardware to halt */
err = xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val,
(val & XILINX_DMA_DMASR_HALTED), 0,
return xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val,
val & XILINX_DMA_DMASR_HALTED, 0,
XILINX_DMA_LOOP_COUNT);
if (err) {
dev_err(chan->dev, "Cannot stop channel %p: %x\n",
chan, dma_ctrl_read(chan, XILINX_DMA_REG_DMASR));
chan->err = true;
}
/**
* xilinx_cdma_stop_transfer - Wait for the current transfer to complete
* @chan: Driver specific DMA channel
*/
static int xilinx_cdma_stop_transfer(struct xilinx_dma_chan *chan)
{
u32 val;
return xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val,
val & XILINX_DMA_DMASR_IDLE, 0,
XILINX_DMA_LOOP_COUNT);
}
/**
@ -1653,7 +1661,7 @@ xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst,
{
struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
struct xilinx_dma_tx_descriptor *desc;
struct xilinx_cdma_tx_segment *segment, *prev;
struct xilinx_cdma_tx_segment *segment;
struct xilinx_cdma_desc_hw *hw;
if (!len || len > XILINX_DMA_MAX_TRANS_LEN)
@ -1680,21 +1688,11 @@ xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst,
hw->dest_addr_msb = upper_32_bits(dma_dst);
}
/* Fill the previous next descriptor with current */
prev = list_last_entry(&desc->segments,
struct xilinx_cdma_tx_segment, node);
prev->hw.next_desc = segment->phys;
/* Insert the segment into the descriptor segments list. */
list_add_tail(&segment->node, &desc->segments);
prev = segment;
/* Link the last hardware descriptor with the first. */
segment = list_first_entry(&desc->segments,
struct xilinx_cdma_tx_segment, node);
desc->async_tx.phys = segment->phys;
prev->hw.next_desc = segment->phys;
hw->next_desc = segment->phys;
return &desc->async_tx;
@ -2003,12 +2001,17 @@ static int xilinx_dma_terminate_all(struct dma_chan *dchan)
{
struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
u32 reg;
int err;
if (chan->cyclic)
xilinx_dma_chan_reset(chan);
/* Halt the DMA engine */
xilinx_dma_halt(chan);
err = chan->stop_transfer(chan);
if (err) {
dev_err(chan->dev, "Cannot stop channel %p: %x\n",
chan, dma_ctrl_read(chan, XILINX_DMA_REG_DMASR));
chan->err = true;
}
/* Remove and free all of the descriptors in the lists */
xilinx_dma_free_descriptors(chan);
@ -2397,12 +2400,16 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
return err;
}
if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
chan->start_transfer = xilinx_dma_start_transfer;
else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA)
chan->stop_transfer = xilinx_dma_stop_transfer;
} else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
chan->start_transfer = xilinx_cdma_start_transfer;
else
chan->stop_transfer = xilinx_cdma_stop_transfer;
} else {
chan->start_transfer = xilinx_vdma_start_transfer;
chan->stop_transfer = xilinx_dma_stop_transfer;
}
/* Initialize the tasklet */
tasklet_init(&chan->tasklet, xilinx_dma_do_tasklet,

View File

@ -38,24 +38,16 @@
#define PL080_SOFT_LSREQ (0x2C)
#define PL080_CONFIG (0x30)
#define PL080_CONFIG_M2_BE (1 << 2)
#define PL080_CONFIG_M1_BE (1 << 1)
#define PL080_CONFIG_ENABLE (1 << 0)
#define PL080_CONFIG_M2_BE BIT(2)
#define PL080_CONFIG_M1_BE BIT(1)
#define PL080_CONFIG_ENABLE BIT(0)
#define PL080_SYNC (0x34)
/* Per channel configuration registers */
#define PL080_Cx_STRIDE (0x20)
/* Per channel configuration registers */
#define PL080_Cx_BASE(x) ((0x100 + (x * 0x20)))
#define PL080_Cx_SRC_ADDR(x) ((0x100 + (x * 0x20)))
#define PL080_Cx_DST_ADDR(x) ((0x104 + (x * 0x20)))
#define PL080_Cx_LLI(x) ((0x108 + (x * 0x20)))
#define PL080_Cx_CONTROL(x) ((0x10C + (x * 0x20)))
#define PL080_Cx_CONFIG(x) ((0x110 + (x * 0x20)))
#define PL080S_Cx_CONTROL2(x) ((0x110 + (x * 0x20)))
#define PL080S_Cx_CONFIG(x) ((0x114 + (x * 0x20)))
#define PL080_CH_SRC_ADDR (0x00)
#define PL080_CH_DST_ADDR (0x04)
#define PL080_CH_LLI (0x08)
@ -66,18 +58,18 @@
#define PL080_LLI_ADDR_MASK (0x3fffffff << 2)
#define PL080_LLI_ADDR_SHIFT (2)
#define PL080_LLI_LM_AHB2 (1 << 0)
#define PL080_LLI_LM_AHB2 BIT(0)
#define PL080_CONTROL_TC_IRQ_EN (1 << 31)
#define PL080_CONTROL_TC_IRQ_EN BIT(31)
#define PL080_CONTROL_PROT_MASK (0x7 << 28)
#define PL080_CONTROL_PROT_SHIFT (28)
#define PL080_CONTROL_PROT_CACHE (1 << 30)
#define PL080_CONTROL_PROT_BUFF (1 << 29)
#define PL080_CONTROL_PROT_SYS (1 << 28)
#define PL080_CONTROL_DST_INCR (1 << 27)
#define PL080_CONTROL_SRC_INCR (1 << 26)
#define PL080_CONTROL_DST_AHB2 (1 << 25)
#define PL080_CONTROL_SRC_AHB2 (1 << 24)
#define PL080_CONTROL_PROT_CACHE BIT(30)
#define PL080_CONTROL_PROT_BUFF BIT(29)
#define PL080_CONTROL_PROT_SYS BIT(28)
#define PL080_CONTROL_DST_INCR BIT(27)
#define PL080_CONTROL_SRC_INCR BIT(26)
#define PL080_CONTROL_DST_AHB2 BIT(25)
#define PL080_CONTROL_SRC_AHB2 BIT(24)
#define PL080_CONTROL_DWIDTH_MASK (0x7 << 21)
#define PL080_CONTROL_DWIDTH_SHIFT (21)
#define PL080_CONTROL_SWIDTH_MASK (0x7 << 18)
@ -103,20 +95,20 @@
#define PL080_WIDTH_16BIT (0x1)
#define PL080_WIDTH_32BIT (0x2)
#define PL080N_CONFIG_ITPROT (1 << 20)
#define PL080N_CONFIG_SECPROT (1 << 19)
#define PL080_CONFIG_HALT (1 << 18)
#define PL080_CONFIG_ACTIVE (1 << 17) /* RO */
#define PL080_CONFIG_LOCK (1 << 16)
#define PL080_CONFIG_TC_IRQ_MASK (1 << 15)
#define PL080_CONFIG_ERR_IRQ_MASK (1 << 14)
#define PL080N_CONFIG_ITPROT BIT(20)
#define PL080N_CONFIG_SECPROT BIT(19)
#define PL080_CONFIG_HALT BIT(18)
#define PL080_CONFIG_ACTIVE BIT(17) /* RO */
#define PL080_CONFIG_LOCK BIT(16)
#define PL080_CONFIG_TC_IRQ_MASK BIT(15)
#define PL080_CONFIG_ERR_IRQ_MASK BIT(14)
#define PL080_CONFIG_FLOW_CONTROL_MASK (0x7 << 11)
#define PL080_CONFIG_FLOW_CONTROL_SHIFT (11)
#define PL080_CONFIG_DST_SEL_MASK (0xf << 6)
#define PL080_CONFIG_DST_SEL_SHIFT (6)
#define PL080_CONFIG_SRC_SEL_MASK (0xf << 1)
#define PL080_CONFIG_SRC_SEL_SHIFT (1)
#define PL080_CONFIG_ENABLE (1 << 0)
#define PL080_CONFIG_ENABLE BIT(0)
#define PL080_FLOW_MEM2MEM (0x0)
#define PL080_FLOW_MEM2PER (0x1)

View File

@ -1,35 +0,0 @@
/* linux/include/linux/amba/pl330.h
*
* Copyright (C) 2010 Samsung Electronics Co. Ltd.
* Jaswinder Singh <jassi.brar@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __AMBA_PL330_H_
#define __AMBA_PL330_H_
#include <linux/dmaengine.h>
struct dma_pl330_platdata {
/*
* Number of valid peripherals connected to DMAC.
* This may be different from the value read from
* CR0, as the PL330 implementation might have 'holes'
* in the peri list or the peri could also be reached
* from another DMAC which the platform prefers.
*/
u8 nr_valid_peri;
/* Array of valid peripherals */
u8 *peri_id;
/* Operational capabilities */
dma_cap_mask_t cap_mask;
/* Bytes to allocate for MC buffer */
unsigned mcbuf_sz;
};
extern bool pl330_filter(struct dma_chan *chan, void *param);
#endif /* __AMBA_PL330_H_ */

View File

@ -1498,7 +1498,7 @@ void debug_dma_alloc_coherent(struct device *dev, size_t size,
entry->type = dma_debug_coherent;
entry->dev = dev;
entry->pfn = page_to_pfn(virt_to_page(virt));
entry->offset = (size_t) virt & ~PAGE_MASK;
entry->offset = offset_in_page(virt);
entry->size = size;
entry->dev_addr = dma_addr;
entry->direction = DMA_BIDIRECTIONAL;
@ -1514,7 +1514,7 @@ void debug_dma_free_coherent(struct device *dev, size_t size,
.type = dma_debug_coherent,
.dev = dev,
.pfn = page_to_pfn(virt_to_page(virt)),
.offset = (size_t) virt & ~PAGE_MASK,
.offset = offset_in_page(virt),
.dev_addr = addr,
.size = size,
.direction = DMA_BIDIRECTIONAL,