Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
9b01029d
Commit
9b01029d
authored
Oct 24, 2018
by
Vinod Koul
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/fsl' into for-linus
parents
11b73fcf
0e819e35
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1247 additions
and
714 deletions
+1247
-714
drivers/dma/Kconfig
drivers/dma/Kconfig
+11
-0
drivers/dma/Makefile
drivers/dma/Makefile
+2
-1
drivers/dma/fsl-edma-common.c
drivers/dma/fsl-edma-common.c
+626
-0
drivers/dma/fsl-edma-common.h
drivers/dma/fsl-edma-common.h
+233
-0
drivers/dma/fsl-edma.c
drivers/dma/fsl-edma.c
+18
-711
drivers/dma/fsldma.c
drivers/dma/fsldma.c
+2
-2
drivers/dma/mcf-edma.c
drivers/dma/mcf-edma.c
+317
-0
include/linux/platform_data/dma-mcf-edma.h
include/linux/platform_data/dma-mcf-edma.h
+38
-0
No files found.
drivers/dma/Kconfig
View file @
9b01029d
...
@@ -321,6 +321,17 @@ config LPC18XX_DMAMUX
...
@@ -321,6 +321,17 @@ config LPC18XX_DMAMUX
Enable support for DMA on NXP LPC18xx/43xx platforms
Enable support for DMA on NXP LPC18xx/43xx platforms
with PL080 and multiplexed DMA request lines.
with PL080 and multiplexed DMA request lines.
config MCF_EDMA
tristate "Freescale eDMA engine support, ColdFire mcf5441x SoCs"
depends on M5441x || COMPILE_TEST
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
help
Support the Freescale ColdFire eDMA engine, 64-channel
implementation that performs complex data transfers with
minimal intervention from a host processor.
This module can be found on Freescale ColdFire mcf5441x SoCs.
config MMP_PDMA
config MMP_PDMA
bool "MMP PDMA support"
bool "MMP PDMA support"
depends on ARCH_MMP || ARCH_PXA || COMPILE_TEST
depends on ARCH_MMP || ARCH_PXA || COMPILE_TEST
...
...
drivers/dma/Makefile
View file @
9b01029d
...
@@ -31,7 +31,8 @@ obj-$(CONFIG_DW_AXI_DMAC) += dw-axi-dmac/
...
@@ -31,7 +31,8 @@ obj-$(CONFIG_DW_AXI_DMAC) += dw-axi-dmac/
obj-$(CONFIG_DW_DMAC_CORE)
+=
dw/
obj-$(CONFIG_DW_DMAC_CORE)
+=
dw/
obj-$(CONFIG_EP93XX_DMA)
+=
ep93xx_dma.o
obj-$(CONFIG_EP93XX_DMA)
+=
ep93xx_dma.o
obj-$(CONFIG_FSL_DMA)
+=
fsldma.o
obj-$(CONFIG_FSL_DMA)
+=
fsldma.o
obj-$(CONFIG_FSL_EDMA)
+=
fsl-edma.o
obj-$(CONFIG_FSL_EDMA)
+=
fsl-edma.o fsl-edma-common.o
obj-$(CONFIG_MCF_EDMA)
+=
mcf-edma.o fsl-edma-common.o
obj-$(CONFIG_FSL_RAID)
+=
fsl_raid.o
obj-$(CONFIG_FSL_RAID)
+=
fsl_raid.o
obj-$(CONFIG_HSU_DMA)
+=
hsu/
obj-$(CONFIG_HSU_DMA)
+=
hsu/
obj-$(CONFIG_IMG_MDC_DMA)
+=
img-mdc-dma.o
obj-$(CONFIG_IMG_MDC_DMA)
+=
img-mdc-dma.o
...
...
drivers/dma/fsl-edma-common.c
0 → 100644
View file @
9b01029d
This diff is collapsed.
Click to expand it.
drivers/dma/fsl-edma-common.h
0 → 100644
View file @
9b01029d
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2013-2014 Freescale Semiconductor, Inc.
* Copyright 2018 Angelo Dureghello <angelo@sysam.it>
*/
#ifndef _FSL_EDMA_COMMON_H_
#define _FSL_EDMA_COMMON_H_
#include "virt-dma.h"
#define EDMA_CR_EDBG BIT(1)
#define EDMA_CR_ERCA BIT(2)
#define EDMA_CR_ERGA BIT(3)
#define EDMA_CR_HOE BIT(4)
#define EDMA_CR_HALT BIT(5)
#define EDMA_CR_CLM BIT(6)
#define EDMA_CR_EMLM BIT(7)
#define EDMA_CR_ECX BIT(16)
#define EDMA_CR_CX BIT(17)
#define EDMA_SEEI_SEEI(x) ((x) & GENMASK(4, 0))
#define EDMA_CEEI_CEEI(x) ((x) & GENMASK(4, 0))
#define EDMA_CINT_CINT(x) ((x) & GENMASK(4, 0))
#define EDMA_CERR_CERR(x) ((x) & GENMASK(4, 0))
#define EDMA_TCD_ATTR_DSIZE(x) (((x) & GENMASK(2, 0)))
#define EDMA_TCD_ATTR_DMOD(x) (((x) & GENMASK(4, 0)) << 3)
#define EDMA_TCD_ATTR_SSIZE(x) (((x) & GENMASK(2, 0)) << 8)
#define EDMA_TCD_ATTR_SMOD(x) (((x) & GENMASK(4, 0)) << 11)
#define EDMA_TCD_ATTR_DSIZE_8BIT 0
#define EDMA_TCD_ATTR_DSIZE_16BIT BIT(0)
#define EDMA_TCD_ATTR_DSIZE_32BIT BIT(1)
#define EDMA_TCD_ATTR_DSIZE_64BIT (BIT(0) | BIT(1))
#define EDMA_TCD_ATTR_DSIZE_32BYTE (BIT(3) | BIT(0))
#define EDMA_TCD_ATTR_SSIZE_8BIT 0
#define EDMA_TCD_ATTR_SSIZE_16BIT (EDMA_TCD_ATTR_DSIZE_16BIT << 8)
#define EDMA_TCD_ATTR_SSIZE_32BIT (EDMA_TCD_ATTR_DSIZE_32BIT << 8)
#define EDMA_TCD_ATTR_SSIZE_64BIT (EDMA_TCD_ATTR_DSIZE_64BIT << 8)
#define EDMA_TCD_ATTR_SSIZE_32BYTE (EDMA_TCD_ATTR_DSIZE_32BYTE << 8)
#define EDMA_TCD_CITER_CITER(x) ((x) & GENMASK(14, 0))
#define EDMA_TCD_BITER_BITER(x) ((x) & GENMASK(14, 0))
#define EDMA_TCD_CSR_START BIT(0)
#define EDMA_TCD_CSR_INT_MAJOR BIT(1)
#define EDMA_TCD_CSR_INT_HALF BIT(2)
#define EDMA_TCD_CSR_D_REQ BIT(3)
#define EDMA_TCD_CSR_E_SG BIT(4)
#define EDMA_TCD_CSR_E_LINK BIT(5)
#define EDMA_TCD_CSR_ACTIVE BIT(6)
#define EDMA_TCD_CSR_DONE BIT(7)
#define EDMAMUX_CHCFG_DIS 0x0
#define EDMAMUX_CHCFG_ENBL 0x80
#define EDMAMUX_CHCFG_SOURCE(n) ((n) & 0x3F)
#define DMAMUX_NR 2
#define FSL_EDMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES))
enum
fsl_edma_pm_state
{
RUNNING
=
0
,
SUSPENDED
,
};
struct
fsl_edma_hw_tcd
{
__le32
saddr
;
__le16
soff
;
__le16
attr
;
__le32
nbytes
;
__le32
slast
;
__le32
daddr
;
__le16
doff
;
__le16
citer
;
__le32
dlast_sga
;
__le16
csr
;
__le16
biter
;
};
/*
* These are iomem pointers, for both v32 and v64.
*/
struct
edma_regs
{
void
__iomem
*
cr
;
void
__iomem
*
es
;
void
__iomem
*
erqh
;
void
__iomem
*
erql
;
/* aka erq on v32 */
void
__iomem
*
eeih
;
void
__iomem
*
eeil
;
/* aka eei on v32 */
void
__iomem
*
seei
;
void
__iomem
*
ceei
;
void
__iomem
*
serq
;
void
__iomem
*
cerq
;
void
__iomem
*
cint
;
void
__iomem
*
cerr
;
void
__iomem
*
ssrt
;
void
__iomem
*
cdne
;
void
__iomem
*
inth
;
void
__iomem
*
intl
;
void
__iomem
*
errh
;
void
__iomem
*
errl
;
struct
fsl_edma_hw_tcd
__iomem
*
tcd
;
};
struct
fsl_edma_sw_tcd
{
dma_addr_t
ptcd
;
struct
fsl_edma_hw_tcd
*
vtcd
;
};
struct
fsl_edma_chan
{
struct
virt_dma_chan
vchan
;
enum
dma_status
status
;
enum
fsl_edma_pm_state
pm_state
;
bool
idle
;
u32
slave_id
;
struct
fsl_edma_engine
*
edma
;
struct
fsl_edma_desc
*
edesc
;
struct
dma_slave_config
cfg
;
u32
attr
;
struct
dma_pool
*
tcd_pool
;
};
struct
fsl_edma_desc
{
struct
virt_dma_desc
vdesc
;
struct
fsl_edma_chan
*
echan
;
bool
iscyclic
;
enum
dma_transfer_direction
dirn
;
unsigned
int
n_tcds
;
struct
fsl_edma_sw_tcd
tcd
[];
};
enum
edma_version
{
v1
,
/* 32ch, Vybdir, mpc57x, etc */
v2
,
/* 64ch Coldfire */
};
struct
fsl_edma_engine
{
struct
dma_device
dma_dev
;
void
__iomem
*
membase
;
void
__iomem
*
muxbase
[
DMAMUX_NR
];
struct
clk
*
muxclk
[
DMAMUX_NR
];
struct
mutex
fsl_edma_mutex
;
u32
n_chans
;
int
txirq
;
int
errirq
;
bool
big_endian
;
enum
edma_version
version
;
struct
edma_regs
regs
;
struct
fsl_edma_chan
chans
[];
};
/*
* R/W functions for big- or little-endian registers:
* The eDMA controller's endian is independent of the CPU core's endian.
* For the big-endian IP module, the offset for 8-bit or 16-bit registers
* should also be swapped opposite to that in little-endian IP.
*/
static
inline
u32
edma_readl
(
struct
fsl_edma_engine
*
edma
,
void
__iomem
*
addr
)
{
if
(
edma
->
big_endian
)
return
ioread32be
(
addr
);
else
return
ioread32
(
addr
);
}
static
inline
void
edma_writeb
(
struct
fsl_edma_engine
*
edma
,
u8
val
,
void
__iomem
*
addr
)
{
/* swap the reg offset for these in big-endian mode */
if
(
edma
->
big_endian
)
iowrite8
(
val
,
(
void
__iomem
*
)((
unsigned
long
)
addr
^
0x3
));
else
iowrite8
(
val
,
addr
);
}
static
inline
void
edma_writew
(
struct
fsl_edma_engine
*
edma
,
u16
val
,
void
__iomem
*
addr
)
{
/* swap the reg offset for these in big-endian mode */
if
(
edma
->
big_endian
)
iowrite16be
(
val
,
(
void
__iomem
*
)((
unsigned
long
)
addr
^
0x2
));
else
iowrite16
(
val
,
addr
);
}
static
inline
void
edma_writel
(
struct
fsl_edma_engine
*
edma
,
u32
val
,
void
__iomem
*
addr
)
{
if
(
edma
->
big_endian
)
iowrite32be
(
val
,
addr
);
else
iowrite32
(
val
,
addr
);
}
static
inline
struct
fsl_edma_chan
*
to_fsl_edma_chan
(
struct
dma_chan
*
chan
)
{
return
container_of
(
chan
,
struct
fsl_edma_chan
,
vchan
.
chan
);
}
static
inline
struct
fsl_edma_desc
*
to_fsl_edma_desc
(
struct
virt_dma_desc
*
vd
)
{
return
container_of
(
vd
,
struct
fsl_edma_desc
,
vdesc
);
}
void
fsl_edma_disable_request
(
struct
fsl_edma_chan
*
fsl_chan
);
void
fsl_edma_chan_mux
(
struct
fsl_edma_chan
*
fsl_chan
,
unsigned
int
slot
,
bool
enable
);
void
fsl_edma_free_desc
(
struct
virt_dma_desc
*
vdesc
);
int
fsl_edma_terminate_all
(
struct
dma_chan
*
chan
);
int
fsl_edma_pause
(
struct
dma_chan
*
chan
);
int
fsl_edma_resume
(
struct
dma_chan
*
chan
);
int
fsl_edma_slave_config
(
struct
dma_chan
*
chan
,
struct
dma_slave_config
*
cfg
);
enum
dma_status
fsl_edma_tx_status
(
struct
dma_chan
*
chan
,
dma_cookie_t
cookie
,
struct
dma_tx_state
*
txstate
);
struct
dma_async_tx_descriptor
*
fsl_edma_prep_dma_cyclic
(
struct
dma_chan
*
chan
,
dma_addr_t
dma_addr
,
size_t
buf_len
,
size_t
period_len
,
enum
dma_transfer_direction
direction
,
unsigned
long
flags
);
struct
dma_async_tx_descriptor
*
fsl_edma_prep_slave_sg
(
struct
dma_chan
*
chan
,
struct
scatterlist
*
sgl
,
unsigned
int
sg_len
,
enum
dma_transfer_direction
direction
,
unsigned
long
flags
,
void
*
context
);
void
fsl_edma_xfer_desc
(
struct
fsl_edma_chan
*
fsl_chan
);
void
fsl_edma_issue_pending
(
struct
dma_chan
*
chan
);
int
fsl_edma_alloc_chan_resources
(
struct
dma_chan
*
chan
);
void
fsl_edma_free_chan_resources
(
struct
dma_chan
*
chan
);
void
fsl_edma_cleanup_vchan
(
struct
dma_device
*
dmadev
);
void
fsl_edma_setup_regs
(
struct
fsl_edma_engine
*
edma
);
#endif
/* _FSL_EDMA_COMMON_H_ */
drivers/dma/fsl-edma.c
View file @
9b01029d
This diff is collapsed.
Click to expand it.
drivers/dma/fsldma.c
View file @
9b01029d
...
@@ -987,7 +987,7 @@ static void dma_do_tasklet(unsigned long data)
...
@@ -987,7 +987,7 @@ static void dma_do_tasklet(unsigned long data)
chan_dbg
(
chan
,
"tasklet entry
\n
"
);
chan_dbg
(
chan
,
"tasklet entry
\n
"
);
spin_lock
_bh
(
&
chan
->
desc_lock
);
spin_lock
(
&
chan
->
desc_lock
);
/* the hardware is now idle and ready for more */
/* the hardware is now idle and ready for more */
chan
->
idle
=
true
;
chan
->
idle
=
true
;
...
@@ -995,7 +995,7 @@ static void dma_do_tasklet(unsigned long data)
...
@@ -995,7 +995,7 @@ static void dma_do_tasklet(unsigned long data)
/* Run all cleanup for descriptors which have been completed */
/* Run all cleanup for descriptors which have been completed */
fsldma_cleanup_descriptors
(
chan
);
fsldma_cleanup_descriptors
(
chan
);
spin_unlock
_bh
(
&
chan
->
desc_lock
);
spin_unlock
(
&
chan
->
desc_lock
);
chan_dbg
(
chan
,
"tasklet exit
\n
"
);
chan_dbg
(
chan
,
"tasklet exit
\n
"
);
}
}
...
...
drivers/dma/mcf-edma.c
0 → 100644
View file @
9b01029d
// SPDX-License-Identifier: GPL-2.0+
//
// Copyright (c) 2013-2014 Freescale Semiconductor, Inc
// Copyright (c) 2017 Sysam, Angelo Dureghello <angelo@sysam.it>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/dmaengine.h>
#include <linux/platform_device.h>
#include <linux/platform_data/dma-mcf-edma.h>
#include "fsl-edma-common.h"
#define EDMA_CHANNELS 64
#define EDMA_MASK_CH(x) ((x) & GENMASK(5, 0))
static
irqreturn_t
mcf_edma_tx_handler
(
int
irq
,
void
*
dev_id
)
{
struct
fsl_edma_engine
*
mcf_edma
=
dev_id
;
struct
edma_regs
*
regs
=
&
mcf_edma
->
regs
;
unsigned
int
ch
;
struct
fsl_edma_chan
*
mcf_chan
;
u64
intmap
;
intmap
=
ioread32
(
regs
->
inth
);
intmap
<<=
32
;
intmap
|=
ioread32
(
regs
->
intl
);
if
(
!
intmap
)
return
IRQ_NONE
;
for
(
ch
=
0
;
ch
<
mcf_edma
->
n_chans
;
ch
++
)
{
if
(
intmap
&
BIT
(
ch
))
{
iowrite8
(
EDMA_MASK_CH
(
ch
),
regs
->
cint
);
mcf_chan
=
&
mcf_edma
->
chans
[
ch
];
spin_lock
(
&
mcf_chan
->
vchan
.
lock
);
if
(
!
mcf_chan
->
edesc
->
iscyclic
)
{
list_del
(
&
mcf_chan
->
edesc
->
vdesc
.
node
);
vchan_cookie_complete
(
&
mcf_chan
->
edesc
->
vdesc
);
mcf_chan
->
edesc
=
NULL
;
mcf_chan
->
status
=
DMA_COMPLETE
;
mcf_chan
->
idle
=
true
;
}
else
{
vchan_cyclic_callback
(
&
mcf_chan
->
edesc
->
vdesc
);
}
if
(
!
mcf_chan
->
edesc
)
fsl_edma_xfer_desc
(
mcf_chan
);
spin_unlock
(
&
mcf_chan
->
vchan
.
lock
);
}
}
return
IRQ_HANDLED
;
}
static
irqreturn_t
mcf_edma_err_handler
(
int
irq
,
void
*
dev_id
)
{
struct
fsl_edma_engine
*
mcf_edma
=
dev_id
;
struct
edma_regs
*
regs
=
&
mcf_edma
->
regs
;
unsigned
int
err
,
ch
;
err
=
ioread32
(
regs
->
errl
);
if
(
!
err
)
return
IRQ_NONE
;
for
(
ch
=
0
;
ch
<
(
EDMA_CHANNELS
/
2
);
ch
++
)
{
if
(
err
&
BIT
(
ch
))
{
fsl_edma_disable_request
(
&
mcf_edma
->
chans
[
ch
]);
iowrite8
(
EDMA_CERR_CERR
(
ch
),
regs
->
cerr
);
mcf_edma
->
chans
[
ch
].
status
=
DMA_ERROR
;
mcf_edma
->
chans
[
ch
].
idle
=
true
;
}
}
err
=
ioread32
(
regs
->
errh
);
if
(
!
err
)
return
IRQ_NONE
;
for
(
ch
=
(
EDMA_CHANNELS
/
2
);
ch
<
EDMA_CHANNELS
;
ch
++
)
{
if
(
err
&
(
BIT
(
ch
-
(
EDMA_CHANNELS
/
2
))))
{
fsl_edma_disable_request
(
&
mcf_edma
->
chans
[
ch
]);
iowrite8
(
EDMA_CERR_CERR
(
ch
),
regs
->
cerr
);
mcf_edma
->
chans
[
ch
].
status
=
DMA_ERROR
;
mcf_edma
->
chans
[
ch
].
idle
=
true
;
}
}
return
IRQ_HANDLED
;
}
static
int
mcf_edma_irq_init
(
struct
platform_device
*
pdev
,
struct
fsl_edma_engine
*
mcf_edma
)
{
int
ret
=
0
,
i
;
struct
resource
*
res
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_IRQ
,
"edma-tx-00-15"
);
if
(
!
res
)
return
-
1
;
for
(
ret
=
0
,
i
=
res
->
start
;
i
<=
res
->
end
;
++
i
)
ret
|=
request_irq
(
i
,
mcf_edma_tx_handler
,
0
,
"eDMA"
,
mcf_edma
);
if
(
ret
)
return
ret
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_IRQ
,
"edma-tx-16-55"
);
if
(
!
res
)
return
-
1
;
for
(
ret
=
0
,
i
=
res
->
start
;
i
<=
res
->
end
;
++
i
)
ret
|=
request_irq
(
i
,
mcf_edma_tx_handler
,
0
,
"eDMA"
,
mcf_edma
);
if
(
ret
)
return
ret
;
ret
=
platform_get_irq_byname
(
pdev
,
"edma-tx-56-63"
);
if
(
ret
!=
-
ENXIO
)
{
ret
=
request_irq
(
ret
,
mcf_edma_tx_handler
,
0
,
"eDMA"
,
mcf_edma
);
if
(
ret
)
return
ret
;
}
ret
=
platform_get_irq_byname
(
pdev
,
"edma-err"
);
if
(
ret
!=
-
ENXIO
)
{
ret
=
request_irq
(
ret
,
mcf_edma_err_handler
,
0
,
"eDMA"
,
mcf_edma
);
if
(
ret
)
return
ret
;
}
return
0
;
}
static
void
mcf_edma_irq_free
(
struct
platform_device
*
pdev
,
struct
fsl_edma_engine
*
mcf_edma
)
{
int
irq
;
struct
resource
*
res
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_IRQ
,
"edma-tx-00-15"
);
if
(
res
)
{
for
(
irq
=
res
->
start
;
irq
<=
res
->
end
;
irq
++
)
free_irq
(
irq
,
mcf_edma
);
}
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_IRQ
,
"edma-tx-16-55"
);
if
(
res
)
{
for
(
irq
=
res
->
start
;
irq
<=
res
->
end
;
irq
++
)
free_irq
(
irq
,
mcf_edma
);
}
irq
=
platform_get_irq_byname
(
pdev
,
"edma-tx-56-63"
);
if
(
irq
!=
-
ENXIO
)
free_irq
(
irq
,
mcf_edma
);
irq
=
platform_get_irq_byname
(
pdev
,
"edma-err"
);
if
(
irq
!=
-
ENXIO
)
free_irq
(
irq
,
mcf_edma
);
}
static
int
mcf_edma_probe
(
struct
platform_device
*
pdev
)
{
struct
mcf_edma_platform_data
*
pdata
;
struct
fsl_edma_engine
*
mcf_edma
;
struct
fsl_edma_chan
*
mcf_chan
;
struct
edma_regs
*
regs
;
struct
resource
*
res
;
int
ret
,
i
,
len
,
chans
;
pdata
=
dev_get_platdata
(
&
pdev
->
dev
);
if
(
!
pdata
)
{
dev_err
(
&
pdev
->
dev
,
"no platform data supplied
\n
"
);
return
-
EINVAL
;
}
chans
=
pdata
->
dma_channels
;
len
=
sizeof
(
*
mcf_edma
)
+
sizeof
(
*
mcf_chan
)
*
chans
;
mcf_edma
=
devm_kzalloc
(
&
pdev
->
dev
,
len
,
GFP_KERNEL
);
if
(
!
mcf_edma
)
return
-
ENOMEM
;
mcf_edma
->
n_chans
=
chans
;
/* Set up version for ColdFire edma */
mcf_edma
->
version
=
v2
;
mcf_edma
->
big_endian
=
1
;
if
(
!
mcf_edma
->
n_chans
)
{
dev_info
(
&
pdev
->
dev
,
"setting default channel number to 64"
);
mcf_edma
->
n_chans
=
64
;
}
mutex_init
(
&
mcf_edma
->
fsl_edma_mutex
);
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
mcf_edma
->
membase
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
mcf_edma
->
membase
))
return
PTR_ERR
(
mcf_edma
->
membase
);
fsl_edma_setup_regs
(
mcf_edma
);
regs
=
&
mcf_edma
->
regs
;
INIT_LIST_HEAD
(
&
mcf_edma
->
dma_dev
.
channels
);
for
(
i
=
0
;
i
<
mcf_edma
->
n_chans
;
i
++
)
{
struct
fsl_edma_chan
*
mcf_chan
=
&
mcf_edma
->
chans
[
i
];
mcf_chan
->
edma
=
mcf_edma
;
mcf_chan
->
slave_id
=
i
;
mcf_chan
->
idle
=
true
;
mcf_chan
->
vchan
.
desc_free
=
fsl_edma_free_desc
;
vchan_init
(
&
mcf_chan
->
vchan
,
&
mcf_edma
->
dma_dev
);
iowrite32
(
0x0
,
&
regs
->
tcd
[
i
].
csr
);
}
iowrite32
(
~
0
,
regs
->
inth
);
iowrite32
(
~
0
,
regs
->
intl
);
ret
=
mcf_edma_irq_init
(
pdev
,
mcf_edma
);
if
(
ret
)
return
ret
;
dma_cap_set
(
DMA_PRIVATE
,
mcf_edma
->
dma_dev
.
cap_mask
);
dma_cap_set
(
DMA_SLAVE
,
mcf_edma
->
dma_dev
.
cap_mask
);
dma_cap_set
(
DMA_CYCLIC
,
mcf_edma
->
dma_dev
.
cap_mask
);
mcf_edma
->
dma_dev
.
dev
=
&
pdev
->
dev
;
mcf_edma
->
dma_dev
.
device_alloc_chan_resources
=
fsl_edma_alloc_chan_resources
;
mcf_edma
->
dma_dev
.
device_free_chan_resources
=
fsl_edma_free_chan_resources
;
mcf_edma
->
dma_dev
.
device_config
=
fsl_edma_slave_config
;
mcf_edma
->
dma_dev
.
device_prep_dma_cyclic
=
fsl_edma_prep_dma_cyclic
;
mcf_edma
->
dma_dev
.
device_prep_slave_sg
=
fsl_edma_prep_slave_sg
;
mcf_edma
->
dma_dev
.
device_tx_status
=
fsl_edma_tx_status
;
mcf_edma
->
dma_dev
.
device_pause
=
fsl_edma_pause
;
mcf_edma
->
dma_dev
.
device_resume
=
fsl_edma_resume
;
mcf_edma
->
dma_dev
.
device_terminate_all
=
fsl_edma_terminate_all
;
mcf_edma
->
dma_dev
.
device_issue_pending
=
fsl_edma_issue_pending
;
mcf_edma
->
dma_dev
.
src_addr_widths
=
FSL_EDMA_BUSWIDTHS
;
mcf_edma
->
dma_dev
.
dst_addr_widths
=
FSL_EDMA_BUSWIDTHS
;
mcf_edma
->
dma_dev
.
directions
=
BIT
(
DMA_DEV_TO_MEM
)
|
BIT
(
DMA_MEM_TO_DEV
);
mcf_edma
->
dma_dev
.
filter
.
fn
=
mcf_edma_filter_fn
;
mcf_edma
->
dma_dev
.
filter
.
map
=
pdata
->
slave_map
;
mcf_edma
->
dma_dev
.
filter
.
mapcnt
=
pdata
->
slavecnt
;
platform_set_drvdata
(
pdev
,
mcf_edma
);
ret
=
dma_async_device_register
(
&
mcf_edma
->
dma_dev
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"Can't register Freescale eDMA engine. (%d)
\n
"
,
ret
);
return
ret
;
}
/* Enable round robin arbitration */
iowrite32
(
EDMA_CR_ERGA
|
EDMA_CR_ERCA
,
regs
->
cr
);
return
0
;
}
static
int
mcf_edma_remove
(
struct
platform_device
*
pdev
)
{
struct
fsl_edma_engine
*
mcf_edma
=
platform_get_drvdata
(
pdev
);
mcf_edma_irq_free
(
pdev
,
mcf_edma
);
fsl_edma_cleanup_vchan
(
&
mcf_edma
->
dma_dev
);
dma_async_device_unregister
(
&
mcf_edma
->
dma_dev
);
return
0
;
}
static
struct
platform_driver
mcf_edma_driver
=
{
.
driver
=
{
.
name
=
"mcf-edma"
,
},
.
probe
=
mcf_edma_probe
,
.
remove
=
mcf_edma_remove
,
};
bool
mcf_edma_filter_fn
(
struct
dma_chan
*
chan
,
void
*
param
)
{
if
(
chan
->
device
->
dev
->
driver
==
&
mcf_edma_driver
.
driver
)
{
struct
fsl_edma_chan
*
mcf_chan
=
to_fsl_edma_chan
(
chan
);
return
(
mcf_chan
->
slave_id
==
(
uintptr_t
)
param
);
}
return
false
;
}
EXPORT_SYMBOL
(
mcf_edma_filter_fn
);
static
int
__init
mcf_edma_init
(
void
)
{
return
platform_driver_register
(
&
mcf_edma_driver
);
}
subsys_initcall
(
mcf_edma_init
);
static
void
__exit
mcf_edma_exit
(
void
)
{
platform_driver_unregister
(
&
mcf_edma_driver
);
}
module_exit
(
mcf_edma_exit
);
MODULE_ALIAS
(
"platform:mcf-edma"
);
MODULE_DESCRIPTION
(
"Freescale eDMA engine driver, ColdFire family"
);
MODULE_LICENSE
(
"GPL v2"
);
include/linux/platform_data/dma-mcf-edma.h
0 → 100644
View file @
9b01029d
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Freescale eDMA platform data, ColdFire SoC's family.
*
* Copyright (c) 2017 Angelo Dureghello <angelo@sysam.it>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __LINUX_PLATFORM_DATA_MCF_EDMA_H__
#define __LINUX_PLATFORM_DATA_MCF_EDMA_H__
struct
dma_slave_map
;
bool
mcf_edma_filter_fn
(
struct
dma_chan
*
chan
,
void
*
param
);
#define MCF_EDMA_FILTER_PARAM(ch) ((void *)ch)
/**
* struct mcf_edma_platform_data - platform specific data for eDMA engine
*
* @ver The eDMA module version.
* @dma_channels The number of eDMA channels.
*/
struct
mcf_edma_platform_data
{
int
dma_channels
;
const
struct
dma_slave_map
*
slave_map
;
int
slavecnt
;
};
#endif
/* __LINUX_PLATFORM_DATA_MCF_EDMA_H__ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment