Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
4b4447bf
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
4b4447bf
编写于
10月 24, 2018
作者:
V
Vinod Koul
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'topic/sprd' into for-linus
上级
8e75ab9b
4ac69546
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
143 addition
and
7 deletion
+143
-7
drivers/dma/sprd-dma.c
drivers/dma/sprd-dma.c
+74
-7
include/linux/dma/sprd-dma.h
include/linux/dma/sprd-dma.h
+69
-0
未找到文件。
drivers/dma/sprd-dma.c
浏览文件 @
4b4447bf
...
...
@@ -68,6 +68,7 @@
/* SPRD_DMA_CHN_CFG register definition */
#define SPRD_DMA_CHN_EN BIT(0)
#define SPRD_DMA_LINKLIST_EN BIT(4)
#define SPRD_DMA_WAIT_BDONE_OFFSET 24
#define SPRD_DMA_DONOT_WAIT_BDONE 1
...
...
@@ -103,7 +104,7 @@
#define SPRD_DMA_REQ_MODE_MASK GENMASK(1, 0)
#define SPRD_DMA_FIX_SEL_OFFSET 21
#define SPRD_DMA_FIX_EN_OFFSET 20
#define SPRD_DMA_LLIST_END
_OFFSET 19
#define SPRD_DMA_LLIST_END
BIT(19)
#define SPRD_DMA_FRG_LEN_MASK GENMASK(16, 0)
/* SPRD_DMA_CHN_BLK_LEN register definition */
...
...
@@ -164,6 +165,7 @@ struct sprd_dma_desc {
struct
sprd_dma_chn
{
struct
virt_dma_chan
vc
;
void
__iomem
*
chn_base
;
struct
sprd_dma_linklist
linklist
;
struct
dma_slave_config
slave_cfg
;
u32
chn_num
;
u32
dev_id
;
...
...
@@ -582,7 +584,8 @@ static int sprd_dma_get_step(enum dma_slave_buswidth buswidth)
}
static
int
sprd_dma_fill_desc
(
struct
dma_chan
*
chan
,
struct
sprd_dma_desc
*
sdesc
,
struct
sprd_dma_chn_hw
*
hw
,
unsigned
int
sglen
,
int
sg_index
,
dma_addr_t
src
,
dma_addr_t
dst
,
u32
len
,
enum
dma_transfer_direction
dir
,
unsigned
long
flags
,
...
...
@@ -590,7 +593,6 @@ static int sprd_dma_fill_desc(struct dma_chan *chan,
{
struct
sprd_dma_dev
*
sdev
=
to_sprd_dma_dev
(
chan
);
struct
sprd_dma_chn
*
schan
=
to_sprd_dma_chan
(
chan
);
struct
sprd_dma_chn_hw
*
hw
=
&
sdesc
->
chn_hw
;
u32
req_mode
=
(
flags
>>
SPRD_DMA_REQ_SHIFT
)
&
SPRD_DMA_REQ_MODE_MASK
;
u32
int_mode
=
flags
&
SPRD_DMA_INT_MASK
;
int
src_datawidth
,
dst_datawidth
,
src_step
,
dst_step
;
...
...
@@ -670,12 +672,52 @@ static int sprd_dma_fill_desc(struct dma_chan *chan,
temp
|=
(
src_step
&
SPRD_DMA_TRSF_STEP_MASK
)
<<
SPRD_DMA_SRC_TRSF_STEP_OFFSET
;
hw
->
trsf_step
=
temp
;
/* link-list configuration */
if
(
schan
->
linklist
.
phy_addr
)
{
if
(
sg_index
==
sglen
-
1
)
hw
->
frg_len
|=
SPRD_DMA_LLIST_END
;
hw
->
cfg
|=
SPRD_DMA_LINKLIST_EN
;
/* link-list index */
temp
=
(
sg_index
+
1
)
%
sglen
;
/* Next link-list configuration's physical address offset */
temp
=
temp
*
sizeof
(
*
hw
)
+
SPRD_DMA_CHN_SRC_ADDR
;
/*
* Set the link-list pointer point to next link-list
* configuration's physical address.
*/
hw
->
llist_ptr
=
schan
->
linklist
.
phy_addr
+
temp
;
}
else
{
hw
->
llist_ptr
=
0
;
}
hw
->
frg_step
=
0
;
hw
->
src_blk_step
=
0
;
hw
->
des_blk_step
=
0
;
return
0
;
}
static
int
sprd_dma_fill_linklist_desc
(
struct
dma_chan
*
chan
,
unsigned
int
sglen
,
int
sg_index
,
dma_addr_t
src
,
dma_addr_t
dst
,
u32
len
,
enum
dma_transfer_direction
dir
,
unsigned
long
flags
,
struct
dma_slave_config
*
slave_cfg
)
{
struct
sprd_dma_chn
*
schan
=
to_sprd_dma_chan
(
chan
);
struct
sprd_dma_chn_hw
*
hw
;
if
(
!
schan
->
linklist
.
virt_addr
)
return
-
EINVAL
;
hw
=
(
struct
sprd_dma_chn_hw
*
)(
schan
->
linklist
.
virt_addr
+
sg_index
*
sizeof
(
*
hw
));
return
sprd_dma_fill_desc
(
chan
,
hw
,
sglen
,
sg_index
,
src
,
dst
,
len
,
dir
,
flags
,
slave_cfg
);
}
static
struct
dma_async_tx_descriptor
*
sprd_dma_prep_dma_memcpy
(
struct
dma_chan
*
chan
,
dma_addr_t
dest
,
dma_addr_t
src
,
size_t
len
,
unsigned
long
flags
)
...
...
@@ -744,10 +786,20 @@ sprd_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
u32
len
=
0
;
int
ret
,
i
;
/* TODO: now we only support one sg for each DMA configuration. */
if
(
!
is_slave_direction
(
dir
)
||
sglen
>
1
)
if
(
!
is_slave_direction
(
dir
))
return
NULL
;
if
(
context
)
{
struct
sprd_dma_linklist
*
ll_cfg
=
(
struct
sprd_dma_linklist
*
)
context
;
schan
->
linklist
.
phy_addr
=
ll_cfg
->
phy_addr
;
schan
->
linklist
.
virt_addr
=
ll_cfg
->
virt_addr
;
}
else
{
schan
->
linklist
.
phy_addr
=
0
;
schan
->
linklist
.
virt_addr
=
0
;
}
sdesc
=
kzalloc
(
sizeof
(
*
sdesc
),
GFP_NOWAIT
);
if
(
!
sdesc
)
return
NULL
;
...
...
@@ -762,10 +814,25 @@ sprd_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
src
=
slave_cfg
->
src_addr
;
dst
=
sg_dma_address
(
sg
);
}
/*
* The link-list mode needs at least 2 link-list
* configurations. If there is only one sg, it doesn't
* need to fill the link-list configuration.
*/
if
(
sglen
<
2
)
break
;
ret
=
sprd_dma_fill_linklist_desc
(
chan
,
sglen
,
i
,
src
,
dst
,
len
,
dir
,
flags
,
slave_cfg
);
if
(
ret
)
{
kfree
(
sdesc
);
return
NULL
;
}
}
ret
=
sprd_dma_fill_desc
(
chan
,
sdesc
,
src
,
dst
,
len
,
dir
,
flags
,
slave_cfg
);
ret
=
sprd_dma_fill_desc
(
chan
,
&
sdesc
->
chn_hw
,
0
,
0
,
src
,
dst
,
len
,
dir
,
flags
,
slave_cfg
);
if
(
ret
)
{
kfree
(
sdesc
);
return
NULL
;
...
...
include/linux/dma/sprd-dma.h
浏览文件 @
4b4447bf
...
...
@@ -58,4 +58,73 @@ enum sprd_dma_int_type {
SPRD_DMA_CFGERR_INT
,
};
/*
* struct sprd_dma_linklist - DMA link-list address structure
* @virt_addr: link-list virtual address to configure link-list node
* @phy_addr: link-list physical address to link DMA transfer
*
* The Spreadtrum DMA controller supports the link-list mode, that means slaves
* can supply several groups configurations (each configuration represents one
* DMA transfer) saved in memory, and DMA controller will link these groups
* configurations by writing the physical address of each configuration into the
* link-list register.
*
* Just as shown below, the link-list pointer register will be pointed to the
* physical address of 'configuration 1', and the 'configuration 1' link-list
* pointer will be pointed to 'configuration 2', and so on.
* Once trigger the DMA transfer, the DMA controller will load 'configuration
* 1' to its registers automatically, after 'configuration 1' transaction is
* done, DMA controller will load 'configuration 2' automatically, until all
* DMA transactions are done.
*
* Note: The last link-list pointer should point to the physical address
* of 'configuration 1', which can avoid DMA controller loads incorrect
* configuration when the last configuration transaction is done.
*
* DMA controller linklist memory
* ====================== -----------------------
*| | | configuration 1 |<---
*| DMA controller | ------->| | |
*| | | | | |
*| | | | | |
*| | | | | |
*| linklist pointer reg |---- ----| linklist pointer | |
* ====================== | ----------------------- |
* | |
* | ----------------------- |
* | | configuration 2 | |
* --->| | |
* | | |
* | | |
* | | |
* ----| linklist pointer | |
* | ----------------------- |
* | |
* | ----------------------- |
* | | configuration 3 | |
* --->| | |
* | | |
* | . | |
* . |
* . |
* . |
* | . |
* | ----------------------- |
* | | configuration n | |
* --->| | |
* | | |
* | | |
* | | |
* | linklist pointer |----
* -----------------------
*
* To support the link-list mode, DMA slaves should allocate one segment memory
* from always-on IRAM or dma coherent memory to store these groups of DMA
* configuration, and pass the virtual and physical address to DMA controller.
*/
struct
sprd_dma_linklist
{
unsigned
long
virt_addr
;
phys_addr_t
phy_addr
;
};
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录