mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 09:19:51 +00:00
dmaengine: ste_dma40: Supply full Device Tree parsing support
Using the new DMA DT bindings and API, we can register the DMA40 driver as Device Tree capable. Now, when a client attempts to allocate a channel using the DMA DT bindings via its own node, we are able to parse the request and allocate a channel in the correct manner. Cc: Dan Williams <djbw@fb.com> Cc: Per Forlin <per.forlin@stericsson.com> Cc: Rabin Vincent <rabin@rab.in> Cc: Rob Herring <rob.herring@calxeda.com> Cc: devicetree-discuss@lists.ozlabs.org Acked-by: Vinod Koul <vinod.koul@intel.com> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
1814a1703c
commit
fa332de5c6
2 changed files with 114 additions and 0 deletions
62
Documentation/devicetree/bindings/dma/ste-dma40.txt
Normal file
62
Documentation/devicetree/bindings/dma/ste-dma40.txt
Normal file
|
@ -0,0 +1,62 @@
|
|||
* DMA40 DMA Controller
|
||||
|
||||
Required properties:
|
||||
- compatible: "stericsson,dma40"
|
||||
- reg: Address range of the DMAC registers
|
||||
- reg-names: Names of the above areas to use during resource look-up
|
||||
- interrupt: Should contain the DMAC interrupt number
|
||||
- #dma-cells: must be <3>
|
||||
|
||||
Optional properties:
|
||||
- dma-channels: Number of channels supported by hardware - if not present
|
||||
the driver will attempt to obtain the information from H/W
|
||||
|
||||
Example:
|
||||
|
||||
dma: dma-controller@801C0000 {
|
||||
compatible = "stericsson,db8500-dma40", "stericsson,dma40";
|
||||
reg = <0x801C0000 0x1000 0x40010000 0x800>;
|
||||
reg-names = "base", "lcpa";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 25 0x4>;
|
||||
|
||||
#dma-cells = <2>;
|
||||
dma-channels = <8>;
|
||||
};
|
||||
|
||||
Clients
|
||||
Required properties:
|
||||
- dmas: Comma separated list of dma channel requests
|
||||
- dma-names: Names of the aforementioned requested channels
|
||||
|
||||
Each dmas request consists of 4 cells:
|
||||
1. A phandle pointing to the DMA controller
|
||||
2. Device Type
|
||||
3. The DMA request line number (only when 'use fixed channel' is set)
|
||||
4. A 32bit mask specifying; mode, direction and endianess [NB: This list will grow]
|
||||
0x00000001: Mode:
|
||||
Logical channel when unset
|
||||
Physical channel when set
|
||||
0x00000002: Direction:
|
||||
Memory to Device when unset
|
||||
Device to Memory when set
|
||||
0x00000004: Endianess:
|
||||
Little endian when unset
|
||||
Big endian when set
|
||||
0x00000008: Use fixed channel:
|
||||
Use automatic channel selection when unset
|
||||
Use DMA request line number when set
|
||||
|
||||
Example:
|
||||
|
||||
uart@80120000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x80120000 0x1000>;
|
||||
interrupts = <0 11 0x4>;
|
||||
|
||||
dmas = <&dma 13 0 0x2>, /* Logical - DevToMem */
|
||||
<&dma 13 0 0x0>; /* Logical - MemToDev */
|
||||
dma-names = "rx", "rx";
|
||||
|
||||
status = "disabled";
|
||||
};
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_dma.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/platform_data/dma-ste-dma40.h>
|
||||
|
@ -2422,6 +2423,50 @@ static void d40_set_prio_realtime(struct d40_chan *d40c)
|
|||
__d40_set_prio_rt(d40c, d40c->dma_cfg.dev_type, false);
|
||||
}
|
||||
|
||||
#define D40_DT_FLAGS_MODE(flags) ((flags >> 0) & 0x1)
|
||||
#define D40_DT_FLAGS_DIR(flags) ((flags >> 1) & 0x1)
|
||||
#define D40_DT_FLAGS_BIG_ENDIAN(flags) ((flags >> 2) & 0x1)
|
||||
#define D40_DT_FLAGS_FIXED_CHAN(flags) ((flags >> 3) & 0x1)
|
||||
|
||||
static struct dma_chan *d40_xlate(struct of_phandle_args *dma_spec,
|
||||
struct of_dma *ofdma)
|
||||
{
|
||||
struct stedma40_chan_cfg cfg;
|
||||
dma_cap_mask_t cap;
|
||||
u32 flags;
|
||||
|
||||
memset(&cfg, 0, sizeof(struct stedma40_chan_cfg));
|
||||
|
||||
dma_cap_zero(cap);
|
||||
dma_cap_set(DMA_SLAVE, cap);
|
||||
|
||||
cfg.dev_type = dma_spec->args[0];
|
||||
flags = dma_spec->args[2];
|
||||
|
||||
switch (D40_DT_FLAGS_MODE(flags)) {
|
||||
case 0: cfg.mode = STEDMA40_MODE_LOGICAL; break;
|
||||
case 1: cfg.mode = STEDMA40_MODE_PHYSICAL; break;
|
||||
}
|
||||
|
||||
switch (D40_DT_FLAGS_DIR(flags)) {
|
||||
case 0:
|
||||
cfg.dir = STEDMA40_MEM_TO_PERIPH;
|
||||
cfg.dst_info.big_endian = D40_DT_FLAGS_BIG_ENDIAN(flags);
|
||||
break;
|
||||
case 1:
|
||||
cfg.dir = STEDMA40_PERIPH_TO_MEM;
|
||||
cfg.src_info.big_endian = D40_DT_FLAGS_BIG_ENDIAN(flags);
|
||||
break;
|
||||
}
|
||||
|
||||
if (D40_DT_FLAGS_FIXED_CHAN(flags)) {
|
||||
cfg.phy_channel = dma_spec->args[1];
|
||||
cfg.use_fixed_channel = true;
|
||||
}
|
||||
|
||||
return dma_request_channel(cap, stedma40_filter, &cfg);
|
||||
}
|
||||
|
||||
/* DMA ENGINE functions */
|
||||
static int d40_alloc_chan_resources(struct dma_chan *chan)
|
||||
{
|
||||
|
@ -3638,6 +3683,13 @@ static int __init d40_probe(struct platform_device *pdev)
|
|||
|
||||
d40_hw_init(base);
|
||||
|
||||
if (np) {
|
||||
err = of_dma_controller_register(np, d40_xlate, NULL);
|
||||
if (err && err != -ENODEV)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register of_dma_controller\n");
|
||||
}
|
||||
|
||||
dev_info(base->dev, "initialized\n");
|
||||
return 0;
|
||||
|
||||
|
|
Loading…
Reference in a new issue