Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
e4e48c47
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看板
提交
e4e48c47
编写于
2月 21, 2017
作者:
V
Vinod Koul
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'topic/intel' into for-linus
上级
b802c841
f7c799e9
变更
6
显示空白变更内容
内联
并排
Showing
6 changed file
with
227 addition
and
67 deletion
+227
-67
drivers/dma/dw/core.c
drivers/dma/dw/core.c
+151
-60
drivers/dma/dw/pci.c
drivers/dma/dw/pci.c
+17
-2
drivers/dma/dw/platform.c
drivers/dma/dw/platform.c
+1
-0
drivers/dma/dw/regs.h
drivers/dma/dw/regs.h
+54
-5
include/linux/dma/dw.h
include/linux/dma/dw.h
+2
-0
include/linux/platform_data/dma-dw.h
include/linux/platform_data/dma-dw.h
+2
-0
未找到文件。
drivers/dma/dw/core.c
浏览文件 @
e4e48c47
...
@@ -138,16 +138,32 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc)
...
@@ -138,16 +138,32 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc)
dwc
->
descs_allocated
--
;
dwc
->
descs_allocated
--
;
}
}
static
void
dwc_initialize
(
struct
dw_dma_chan
*
dwc
)
static
void
dwc_initialize_chan_idma32
(
struct
dw_dma_chan
*
dwc
)
{
u32
cfghi
=
0
;
u32
cfglo
=
0
;
/* Set default burst alignment */
cfglo
|=
IDMA32C_CFGL_DST_BURST_ALIGN
|
IDMA32C_CFGL_SRC_BURST_ALIGN
;
/* Low 4 bits of the request lines */
cfghi
|=
IDMA32C_CFGH_DST_PER
(
dwc
->
dws
.
dst_id
&
0xf
);
cfghi
|=
IDMA32C_CFGH_SRC_PER
(
dwc
->
dws
.
src_id
&
0xf
);
/* Request line extension (2 bits) */
cfghi
|=
IDMA32C_CFGH_DST_PER_EXT
(
dwc
->
dws
.
dst_id
>>
4
&
0x3
);
cfghi
|=
IDMA32C_CFGH_SRC_PER_EXT
(
dwc
->
dws
.
src_id
>>
4
&
0x3
);
channel_writel
(
dwc
,
CFG_LO
,
cfglo
);
channel_writel
(
dwc
,
CFG_HI
,
cfghi
);
}
static
void
dwc_initialize_chan_dw
(
struct
dw_dma_chan
*
dwc
)
{
{
struct
dw_dma
*
dw
=
to_dw_dma
(
dwc
->
chan
.
device
);
u32
cfghi
=
DWC_CFGH_FIFO_MODE
;
u32
cfghi
=
DWC_CFGH_FIFO_MODE
;
u32
cfglo
=
DWC_CFGL_CH_PRIOR
(
dwc
->
priority
);
u32
cfglo
=
DWC_CFGL_CH_PRIOR
(
dwc
->
priority
);
bool
hs_polarity
=
dwc
->
dws
.
hs_polarity
;
bool
hs_polarity
=
dwc
->
dws
.
hs_polarity
;
if
(
test_bit
(
DW_DMA_IS_INITIALIZED
,
&
dwc
->
flags
))
return
;
cfghi
|=
DWC_CFGH_DST_PER
(
dwc
->
dws
.
dst_id
);
cfghi
|=
DWC_CFGH_DST_PER
(
dwc
->
dws
.
dst_id
);
cfghi
|=
DWC_CFGH_SRC_PER
(
dwc
->
dws
.
src_id
);
cfghi
|=
DWC_CFGH_SRC_PER
(
dwc
->
dws
.
src_id
);
...
@@ -156,6 +172,19 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
...
@@ -156,6 +172,19 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
channel_writel
(
dwc
,
CFG_LO
,
cfglo
);
channel_writel
(
dwc
,
CFG_LO
,
cfglo
);
channel_writel
(
dwc
,
CFG_HI
,
cfghi
);
channel_writel
(
dwc
,
CFG_HI
,
cfghi
);
}
static
void
dwc_initialize
(
struct
dw_dma_chan
*
dwc
)
{
struct
dw_dma
*
dw
=
to_dw_dma
(
dwc
->
chan
.
device
);
if
(
test_bit
(
DW_DMA_IS_INITIALIZED
,
&
dwc
->
flags
))
return
;
if
(
dw
->
pdata
->
is_idma32
)
dwc_initialize_chan_idma32
(
dwc
);
else
dwc_initialize_chan_dw
(
dwc
);
/* Enable interrupts */
/* Enable interrupts */
channel_set_bit
(
dw
,
MASK
.
XFER
,
dwc
->
mask
);
channel_set_bit
(
dw
,
MASK
.
XFER
,
dwc
->
mask
);
...
@@ -184,6 +213,37 @@ static inline void dwc_chan_disable(struct dw_dma *dw, struct dw_dma_chan *dwc)
...
@@ -184,6 +213,37 @@ static inline void dwc_chan_disable(struct dw_dma *dw, struct dw_dma_chan *dwc)
cpu_relax
();
cpu_relax
();
}
}
static
u32
bytes2block
(
struct
dw_dma_chan
*
dwc
,
size_t
bytes
,
unsigned
int
width
,
size_t
*
len
)
{
struct
dw_dma
*
dw
=
to_dw_dma
(
dwc
->
chan
.
device
);
u32
block
;
/* Always in bytes for iDMA 32-bit */
if
(
dw
->
pdata
->
is_idma32
)
width
=
0
;
if
((
bytes
>>
width
)
>
dwc
->
block_size
)
{
block
=
dwc
->
block_size
;
*
len
=
block
<<
width
;
}
else
{
block
=
bytes
>>
width
;
*
len
=
bytes
;
}
return
block
;
}
static
size_t
block2bytes
(
struct
dw_dma_chan
*
dwc
,
u32
block
,
u32
width
)
{
struct
dw_dma
*
dw
=
to_dw_dma
(
dwc
->
chan
.
device
);
if
(
dw
->
pdata
->
is_idma32
)
return
IDMA32C_CTLH_BLOCK_TS
(
block
);
return
DWC_CTLH_BLOCK_TS
(
block
)
<<
width
;
}
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
/* Perform single block transfer */
/* Perform single block transfer */
...
@@ -332,7 +392,7 @@ static inline u32 dwc_get_sent(struct dw_dma_chan *dwc)
...
@@ -332,7 +392,7 @@ static inline u32 dwc_get_sent(struct dw_dma_chan *dwc)
u32
ctlhi
=
channel_readl
(
dwc
,
CTL_HI
);
u32
ctlhi
=
channel_readl
(
dwc
,
CTL_HI
);
u32
ctllo
=
channel_readl
(
dwc
,
CTL_LO
);
u32
ctllo
=
channel_readl
(
dwc
,
CTL_LO
);
return
(
ctlhi
&
DWC_CTLH_BLOCK_TS_MASK
)
*
(
1
<<
(
ctllo
>>
4
&
7
)
);
return
block2bytes
(
dwc
,
ctlhi
,
ctllo
>>
4
&
7
);
}
}
static
void
dwc_scan_descriptors
(
struct
dw_dma
*
dw
,
struct
dw_dma_chan
*
dwc
)
static
void
dwc_scan_descriptors
(
struct
dw_dma
*
dw
,
struct
dw_dma_chan
*
dwc
)
...
@@ -692,10 +752,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
...
@@ -692,10 +752,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
|
DWC_CTLL_FC_M2M
;
|
DWC_CTLL_FC_M2M
;
prev
=
first
=
NULL
;
prev
=
first
=
NULL
;
for
(
offset
=
0
;
offset
<
len
;
offset
+=
xfer_count
<<
src_width
)
{
for
(
offset
=
0
;
offset
<
len
;
offset
+=
xfer_count
)
{
xfer_count
=
min_t
(
size_t
,
(
len
-
offset
)
>>
src_width
,
dwc
->
block_size
);
desc
=
dwc_desc_get
(
dwc
);
desc
=
dwc_desc_get
(
dwc
);
if
(
!
desc
)
if
(
!
desc
)
goto
err_desc_get
;
goto
err_desc_get
;
...
@@ -703,8 +760,8 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
...
@@ -703,8 +760,8 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
lli_write
(
desc
,
sar
,
src
+
offset
);
lli_write
(
desc
,
sar
,
src
+
offset
);
lli_write
(
desc
,
dar
,
dest
+
offset
);
lli_write
(
desc
,
dar
,
dest
+
offset
);
lli_write
(
desc
,
ctllo
,
ctllo
);
lli_write
(
desc
,
ctllo
,
ctllo
);
lli_write
(
desc
,
ctlhi
,
xfer_count
);
lli_write
(
desc
,
ctlhi
,
bytes2block
(
dwc
,
len
-
offset
,
src_width
,
&
xfer_count
)
);
desc
->
len
=
xfer_count
<<
src_width
;
desc
->
len
=
xfer_count
;
if
(
!
first
)
{
if
(
!
first
)
{
first
=
desc
;
first
=
desc
;
...
@@ -775,7 +832,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
...
@@ -775,7 +832,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
for_each_sg
(
sgl
,
sg
,
sg_len
,
i
)
{
for_each_sg
(
sgl
,
sg
,
sg_len
,
i
)
{
struct
dw_desc
*
desc
;
struct
dw_desc
*
desc
;
u32
len
,
dlen
,
mem
;
u32
len
,
mem
;
size_t
dlen
;
mem
=
sg_dma_address
(
sg
);
mem
=
sg_dma_address
(
sg
);
len
=
sg_dma_len
(
sg
);
len
=
sg_dma_len
(
sg
);
...
@@ -789,17 +847,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
...
@@ -789,17 +847,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
lli_write
(
desc
,
sar
,
mem
);
lli_write
(
desc
,
sar
,
mem
);
lli_write
(
desc
,
dar
,
reg
);
lli_write
(
desc
,
dar
,
reg
);
lli_write
(
desc
,
ctlhi
,
bytes2block
(
dwc
,
len
,
mem_width
,
&
dlen
));
lli_write
(
desc
,
ctllo
,
ctllo
|
DWC_CTLL_SRC_WIDTH
(
mem_width
));
lli_write
(
desc
,
ctllo
,
ctllo
|
DWC_CTLL_SRC_WIDTH
(
mem_width
));
if
((
len
>>
mem_width
)
>
dwc
->
block_size
)
{
dlen
=
dwc
->
block_size
<<
mem_width
;
mem
+=
dlen
;
len
-=
dlen
;
}
else
{
dlen
=
len
;
len
=
0
;
}
lli_write
(
desc
,
ctlhi
,
dlen
>>
mem_width
);
desc
->
len
=
dlen
;
desc
->
len
=
dlen
;
if
(
!
first
)
{
if
(
!
first
)
{
...
@@ -809,6 +858,9 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
...
@@ -809,6 +858,9 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
list_add_tail
(
&
desc
->
desc_node
,
&
first
->
tx_list
);
list_add_tail
(
&
desc
->
desc_node
,
&
first
->
tx_list
);
}
}
prev
=
desc
;
prev
=
desc
;
mem
+=
dlen
;
len
-=
dlen
;
total_len
+=
dlen
;
total_len
+=
dlen
;
if
(
len
)
if
(
len
)
...
@@ -828,13 +880,12 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
...
@@ -828,13 +880,12 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
for_each_sg
(
sgl
,
sg
,
sg_len
,
i
)
{
for_each_sg
(
sgl
,
sg
,
sg_len
,
i
)
{
struct
dw_desc
*
desc
;
struct
dw_desc
*
desc
;
u32
len
,
dlen
,
mem
;
u32
len
,
mem
;
size_t
dlen
;
mem
=
sg_dma_address
(
sg
);
mem
=
sg_dma_address
(
sg
);
len
=
sg_dma_len
(
sg
);
len
=
sg_dma_len
(
sg
);
mem_width
=
__ffs
(
data_width
|
mem
|
len
);
slave_sg_fromdev_fill_desc:
slave_sg_fromdev_fill_desc:
desc
=
dwc_desc_get
(
dwc
);
desc
=
dwc_desc_get
(
dwc
);
if
(
!
desc
)
if
(
!
desc
)
...
@@ -842,16 +893,9 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
...
@@ -842,16 +893,9 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
lli_write
(
desc
,
sar
,
reg
);
lli_write
(
desc
,
sar
,
reg
);
lli_write
(
desc
,
dar
,
mem
);
lli_write
(
desc
,
dar
,
mem
);
lli_write
(
desc
,
ctlhi
,
bytes2block
(
dwc
,
len
,
reg_width
,
&
dlen
));
mem_width
=
__ffs
(
data_width
|
mem
|
dlen
);
lli_write
(
desc
,
ctllo
,
ctllo
|
DWC_CTLL_DST_WIDTH
(
mem_width
));
lli_write
(
desc
,
ctllo
,
ctllo
|
DWC_CTLL_DST_WIDTH
(
mem_width
));
if
((
len
>>
reg_width
)
>
dwc
->
block_size
)
{
dlen
=
dwc
->
block_size
<<
reg_width
;
mem
+=
dlen
;
len
-=
dlen
;
}
else
{
dlen
=
len
;
len
=
0
;
}
lli_write
(
desc
,
ctlhi
,
dlen
>>
reg_width
);
desc
->
len
=
dlen
;
desc
->
len
=
dlen
;
if
(
!
first
)
{
if
(
!
first
)
{
...
@@ -861,6 +905,9 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
...
@@ -861,6 +905,9 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
list_add_tail
(
&
desc
->
desc_node
,
&
first
->
tx_list
);
list_add_tail
(
&
desc
->
desc_node
,
&
first
->
tx_list
);
}
}
prev
=
desc
;
prev
=
desc
;
mem
+=
dlen
;
len
-=
dlen
;
total_len
+=
dlen
;
total_len
+=
dlen
;
if
(
len
)
if
(
len
)
...
@@ -903,25 +950,20 @@ bool dw_dma_filter(struct dma_chan *chan, void *param)
...
@@ -903,25 +950,20 @@ bool dw_dma_filter(struct dma_chan *chan, void *param)
}
}
EXPORT_SYMBOL_GPL
(
dw_dma_filter
);
EXPORT_SYMBOL_GPL
(
dw_dma_filter
);
/*
* Fix sconfig's burst size according to dw_dmac. We need to convert them as:
* 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
*
* NOTE: burst size 2 is not supported by controller.
*
* This can be done by finding least significant bit set: n & (n - 1)
*/
static
inline
void
convert_burst
(
u32
*
maxburst
)
{
if
(
*
maxburst
>
1
)
*
maxburst
=
fls
(
*
maxburst
)
-
2
;
else
*
maxburst
=
0
;
}
static
int
dwc_config
(
struct
dma_chan
*
chan
,
struct
dma_slave_config
*
sconfig
)
static
int
dwc_config
(
struct
dma_chan
*
chan
,
struct
dma_slave_config
*
sconfig
)
{
{
struct
dw_dma_chan
*
dwc
=
to_dw_dma_chan
(
chan
);
struct
dw_dma_chan
*
dwc
=
to_dw_dma_chan
(
chan
);
struct
dma_slave_config
*
sc
=
&
dwc
->
dma_sconfig
;
struct
dw_dma
*
dw
=
to_dw_dma
(
chan
->
device
);
/*
* Fix sconfig's burst size according to dw_dmac. We need to convert
* them as:
* 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
*
* NOTE: burst size 2 is not supported by DesignWare controller.
* iDMA 32-bit supports it.
*/
u32
s
=
dw
->
pdata
->
is_idma32
?
1
:
2
;
/* Check if chan will be configured for slave transfers */
/* Check if chan will be configured for slave transfers */
if
(
!
is_slave_direction
(
sconfig
->
direction
))
if
(
!
is_slave_direction
(
sconfig
->
direction
))
...
@@ -930,28 +972,39 @@ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
...
@@ -930,28 +972,39 @@ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
memcpy
(
&
dwc
->
dma_sconfig
,
sconfig
,
sizeof
(
*
sconfig
));
memcpy
(
&
dwc
->
dma_sconfig
,
sconfig
,
sizeof
(
*
sconfig
));
dwc
->
direction
=
sconfig
->
direction
;
dwc
->
direction
=
sconfig
->
direction
;
convert_burst
(
&
dwc
->
dma_sconfig
.
src_maxburst
)
;
sc
->
src_maxburst
=
sc
->
src_maxburst
>
1
?
fls
(
sc
->
src_maxburst
)
-
s
:
0
;
convert_burst
(
&
dwc
->
dma_sconfig
.
dst_maxburst
)
;
sc
->
dst_maxburst
=
sc
->
dst_maxburst
>
1
?
fls
(
sc
->
dst_maxburst
)
-
s
:
0
;
return
0
;
return
0
;
}
}
static
int
dwc_pause
(
struct
dma_chan
*
cha
n
)
static
void
dwc_chan_pause
(
struct
dw_dma_chan
*
dwc
,
bool
drai
n
)
{
{
struct
dw_dma_chan
*
dwc
=
to_dw_dma_chan
(
chan
);
struct
dw_dma
*
dw
=
to_dw_dma
(
dwc
->
chan
.
device
);
unsigned
long
flags
;
unsigned
int
count
=
20
;
/* timeout iterations */
unsigned
int
count
=
20
;
/* timeout iterations */
u32
cfglo
;
u32
cfglo
;
spin_lock_irqsave
(
&
dwc
->
lock
,
flags
);
cfglo
=
channel_readl
(
dwc
,
CFG_LO
);
cfglo
=
channel_readl
(
dwc
,
CFG_LO
);
if
(
dw
->
pdata
->
is_idma32
)
{
if
(
drain
)
cfglo
|=
IDMA32C_CFGL_CH_DRAIN
;
else
cfglo
&=
~
IDMA32C_CFGL_CH_DRAIN
;
}
channel_writel
(
dwc
,
CFG_LO
,
cfglo
|
DWC_CFGL_CH_SUSP
);
channel_writel
(
dwc
,
CFG_LO
,
cfglo
|
DWC_CFGL_CH_SUSP
);
while
(
!
(
channel_readl
(
dwc
,
CFG_LO
)
&
DWC_CFGL_FIFO_EMPTY
)
&&
count
--
)
while
(
!
(
channel_readl
(
dwc
,
CFG_LO
)
&
DWC_CFGL_FIFO_EMPTY
)
&&
count
--
)
udelay
(
2
);
udelay
(
2
);
set_bit
(
DW_DMA_IS_PAUSED
,
&
dwc
->
flags
);
set_bit
(
DW_DMA_IS_PAUSED
,
&
dwc
->
flags
);
}
static
int
dwc_pause
(
struct
dma_chan
*
chan
)
{
struct
dw_dma_chan
*
dwc
=
to_dw_dma_chan
(
chan
);
unsigned
long
flags
;
spin_lock_irqsave
(
&
dwc
->
lock
,
flags
);
dwc_chan_pause
(
dwc
,
false
);
spin_unlock_irqrestore
(
&
dwc
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
dwc
->
lock
,
flags
);
return
0
;
return
0
;
...
@@ -993,6 +1046,8 @@ static int dwc_terminate_all(struct dma_chan *chan)
...
@@ -993,6 +1046,8 @@ static int dwc_terminate_all(struct dma_chan *chan)
clear_bit
(
DW_DMA_IS_SOFT_LLP
,
&
dwc
->
flags
);
clear_bit
(
DW_DMA_IS_SOFT_LLP
,
&
dwc
->
flags
);
dwc_chan_pause
(
dwc
,
true
);
dwc_chan_disable
(
dw
,
dwc
);
dwc_chan_disable
(
dw
,
dwc
);
dwc_chan_resume
(
dwc
);
dwc_chan_resume
(
dwc
);
...
@@ -1085,6 +1140,32 @@ static void dwc_issue_pending(struct dma_chan *chan)
...
@@ -1085,6 +1140,32 @@ static void dwc_issue_pending(struct dma_chan *chan)
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
/*
* Program FIFO size of channels.
*
* By default full FIFO (1024 bytes) is assigned to channel 0. Here we
* slice FIFO on equal parts between channels.
*/
static
void
idma32_fifo_partition
(
struct
dw_dma
*
dw
)
{
u64
value
=
IDMA32C_FP_PSIZE_CH0
(
128
)
|
IDMA32C_FP_PSIZE_CH1
(
128
)
|
IDMA32C_FP_UPDATE
;
u64
fifo_partition
=
0
;
if
(
!
dw
->
pdata
->
is_idma32
)
return
;
/* Fill FIFO_PARTITION low bits (Channels 0..1, 4..5) */
fifo_partition
|=
value
<<
0
;
/* Fill FIFO_PARTITION high bits (Channels 2..3, 6..7) */
fifo_partition
|=
value
<<
32
;
/* Program FIFO Partition registers - 128 bytes for each channel */
idma32_writeq
(
dw
,
FIFO_PARTITION1
,
fifo_partition
);
idma32_writeq
(
dw
,
FIFO_PARTITION0
,
fifo_partition
);
}
static
void
dw_dma_off
(
struct
dw_dma
*
dw
)
static
void
dw_dma_off
(
struct
dw_dma
*
dw
)
{
{
unsigned
int
i
;
unsigned
int
i
;
...
@@ -1504,8 +1585,16 @@ int dw_dma_probe(struct dw_dma_chip *chip)
...
@@ -1504,8 +1585,16 @@ int dw_dma_probe(struct dw_dma_chip *chip)
/* Force dma off, just in case */
/* Force dma off, just in case */
dw_dma_off
(
dw
);
dw_dma_off
(
dw
);
idma32_fifo_partition
(
dw
);
/* Device and instance ID for IRQ and DMA pool */
if
(
pdata
->
is_idma32
)
snprintf
(
dw
->
name
,
sizeof
(
dw
->
name
),
"idma32:dmac%d"
,
chip
->
id
);
else
snprintf
(
dw
->
name
,
sizeof
(
dw
->
name
),
"dw:dmac%d"
,
chip
->
id
);
/* Create a pool of consistent memory blocks for hardware descriptors */
/* Create a pool of consistent memory blocks for hardware descriptors */
dw
->
desc_pool
=
dmam_pool_create
(
"dw_dmac_desc_pool"
,
chip
->
dev
,
dw
->
desc_pool
=
dmam_pool_create
(
dw
->
name
,
chip
->
dev
,
sizeof
(
struct
dw_desc
),
4
,
0
);
sizeof
(
struct
dw_desc
),
4
,
0
);
if
(
!
dw
->
desc_pool
)
{
if
(
!
dw
->
desc_pool
)
{
dev_err
(
chip
->
dev
,
"No memory for descriptors dma pool
\n
"
);
dev_err
(
chip
->
dev
,
"No memory for descriptors dma pool
\n
"
);
...
@@ -1516,7 +1605,7 @@ int dw_dma_probe(struct dw_dma_chip *chip)
...
@@ -1516,7 +1605,7 @@ int dw_dma_probe(struct dw_dma_chip *chip)
tasklet_init
(
&
dw
->
tasklet
,
dw_dma_tasklet
,
(
unsigned
long
)
dw
);
tasklet_init
(
&
dw
->
tasklet
,
dw_dma_tasklet
,
(
unsigned
long
)
dw
);
err
=
request_irq
(
chip
->
irq
,
dw_dma_interrupt
,
IRQF_SHARED
,
err
=
request_irq
(
chip
->
irq
,
dw_dma_interrupt
,
IRQF_SHARED
,
"dw_dmac"
,
dw
);
dw
->
name
,
dw
);
if
(
err
)
if
(
err
)
goto
err_pdata
;
goto
err_pdata
;
...
@@ -1665,6 +1754,8 @@ int dw_dma_enable(struct dw_dma_chip *chip)
...
@@ -1665,6 +1754,8 @@ int dw_dma_enable(struct dw_dma_chip *chip)
{
{
struct
dw_dma
*
dw
=
chip
->
dw
;
struct
dw_dma
*
dw
=
chip
->
dw
;
idma32_fifo_partition
(
dw
);
dw_dma_on
(
dw
);
dw_dma_on
(
dw
);
return
0
;
return
0
;
}
}
...
...
drivers/dma/dw/pci.c
浏览文件 @
e4e48c47
...
@@ -15,6 +15,18 @@
...
@@ -15,6 +15,18 @@
#include "internal.h"
#include "internal.h"
static
struct
dw_dma_platform_data
mrfld_pdata
=
{
.
nr_channels
=
8
,
.
is_private
=
true
,
.
is_memcpy
=
true
,
.
is_idma32
=
true
,
.
chan_allocation_order
=
CHAN_ALLOCATION_ASCENDING
,
.
chan_priority
=
CHAN_PRIORITY_ASCENDING
,
.
block_size
=
131071
,
.
nr_masters
=
1
,
.
data_width
=
{
4
},
};
static
int
dw_pci_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
pid
)
static
int
dw_pci_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
pid
)
{
{
const
struct
dw_dma_platform_data
*
pdata
=
(
void
*
)
pid
->
driver_data
;
const
struct
dw_dma_platform_data
*
pdata
=
(
void
*
)
pid
->
driver_data
;
...
@@ -47,6 +59,7 @@ static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
...
@@ -47,6 +59,7 @@ static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
return
-
ENOMEM
;
return
-
ENOMEM
;
chip
->
dev
=
&
pdev
->
dev
;
chip
->
dev
=
&
pdev
->
dev
;
chip
->
id
=
pdev
->
devfn
;
chip
->
regs
=
pcim_iomap_table
(
pdev
)[
0
];
chip
->
regs
=
pcim_iomap_table
(
pdev
)[
0
];
chip
->
irq
=
pdev
->
irq
;
chip
->
irq
=
pdev
->
irq
;
chip
->
pdata
=
pdata
;
chip
->
pdata
=
pdata
;
...
@@ -95,14 +108,16 @@ static const struct dev_pm_ops dw_pci_dev_pm_ops = {
...
@@ -95,14 +108,16 @@ static const struct dev_pm_ops dw_pci_dev_pm_ops = {
};
};
static
const
struct
pci_device_id
dw_pci_id_table
[]
=
{
static
const
struct
pci_device_id
dw_pci_id_table
[]
=
{
/* Medfield */
/* Medfield
(GPDMA)
*/
{
PCI_VDEVICE
(
INTEL
,
0x0827
)
},
{
PCI_VDEVICE
(
INTEL
,
0x0827
)
},
{
PCI_VDEVICE
(
INTEL
,
0x0830
)
},
/* BayTrail */
/* BayTrail */
{
PCI_VDEVICE
(
INTEL
,
0x0f06
)
},
{
PCI_VDEVICE
(
INTEL
,
0x0f06
)
},
{
PCI_VDEVICE
(
INTEL
,
0x0f40
)
},
{
PCI_VDEVICE
(
INTEL
,
0x0f40
)
},
/* Merrifield iDMA 32-bit (GPDMA) */
{
PCI_VDEVICE
(
INTEL
,
0x11a2
),
(
kernel_ulong_t
)
&
mrfld_pdata
},
/* Braswell */
/* Braswell */
{
PCI_VDEVICE
(
INTEL
,
0x2286
)
},
{
PCI_VDEVICE
(
INTEL
,
0x2286
)
},
{
PCI_VDEVICE
(
INTEL
,
0x22c0
)
},
{
PCI_VDEVICE
(
INTEL
,
0x22c0
)
},
...
...
drivers/dma/dw/platform.c
浏览文件 @
e4e48c47
...
@@ -202,6 +202,7 @@ static int dw_probe(struct platform_device *pdev)
...
@@ -202,6 +202,7 @@ static int dw_probe(struct platform_device *pdev)
pdata
=
dw_dma_parse_dt
(
pdev
);
pdata
=
dw_dma_parse_dt
(
pdev
);
chip
->
dev
=
dev
;
chip
->
dev
=
dev
;
chip
->
id
=
pdev
->
id
;
chip
->
pdata
=
pdata
;
chip
->
pdata
=
pdata
;
chip
->
clk
=
devm_clk_get
(
chip
->
dev
,
"hclk"
);
chip
->
clk
=
devm_clk_get
(
chip
->
dev
,
"hclk"
);
...
...
drivers/dma/dw/regs.h
浏览文件 @
e4e48c47
...
@@ -3,15 +3,19 @@
...
@@ -3,15 +3,19 @@
*
*
* Copyright (C) 2005-2007 Atmel Corporation
* Copyright (C) 2005-2007 Atmel Corporation
* Copyright (C) 2010-2011 ST Microelectronics
* Copyright (C) 2010-2011 ST Microelectronics
* Copyright (C) 2016 Intel Corporation
*
*
* This program is free software; you can redistribute it and/or modify
* 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
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
* published by the Free Software Foundation.
*/
*/
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/dmaengine.h>
#include <linux/dmaengine.h>
#include <linux/io-64-nonatomic-hi-lo.h>
#include "internal.h"
#include "internal.h"
#define DW_DMA_MAX_NR_REQUESTS 16
#define DW_DMA_MAX_NR_REQUESTS 16
...
@@ -85,9 +89,9 @@ struct dw_dma_regs {
...
@@ -85,9 +89,9 @@ struct dw_dma_regs {
DW_REG
(
ID
);
DW_REG
(
ID
);
DW_REG
(
TEST
);
DW_REG
(
TEST
);
/*
reserved
*/
/*
iDMA 32-bit support
*/
DW_REG
(
__reserved
0
);
DW_REG
(
CLASS_PRIORITY
0
);
DW_REG
(
__reserved
1
);
DW_REG
(
CLASS_PRIORITY
1
);
/* optional encoded params, 0x3c8..0x3f7 */
/* optional encoded params, 0x3c8..0x3f7 */
u32
__reserved
;
u32
__reserved
;
...
@@ -99,6 +103,17 @@ struct dw_dma_regs {
...
@@ -99,6 +103,17 @@ struct dw_dma_regs {
/* top-level parameters */
/* top-level parameters */
u32
DW_PARAMS
;
u32
DW_PARAMS
;
/* component ID */
u32
COMP_TYPE
;
u32
COMP_VERSION
;
/* iDMA 32-bit support */
DW_REG
(
FIFO_PARTITION0
);
DW_REG
(
FIFO_PARTITION1
);
DW_REG
(
SAI_ERR
);
DW_REG
(
GLOBAL_CFG
);
};
};
/*
/*
...
@@ -170,8 +185,9 @@ enum dw_dma_msize {
...
@@ -170,8 +185,9 @@ enum dw_dma_msize {
#define DWC_CTLL_LLP_S_EN (1 << 28)
/* src block chain */
#define DWC_CTLL_LLP_S_EN (1 << 28)
/* src block chain */
/* Bitfields in CTL_HI */
/* Bitfields in CTL_HI */
#define DWC_CTLH_DONE 0x00001000
#define DWC_CTLH_BLOCK_TS_MASK GENMASK(11, 0)
#define DWC_CTLH_BLOCK_TS_MASK 0x00000fff
#define DWC_CTLH_BLOCK_TS(x) ((x) & DWC_CTLH_BLOCK_TS_MASK)
#define DWC_CTLH_DONE (1 << 12)
/* Bitfields in CFG_LO */
/* Bitfields in CFG_LO */
#define DWC_CFGL_CH_PRIOR_MASK (0x7 << 5)
/* priority mask */
#define DWC_CFGL_CH_PRIOR_MASK (0x7 << 5)
/* priority mask */
...
@@ -214,6 +230,33 @@ enum dw_dma_msize {
...
@@ -214,6 +230,33 @@ enum dw_dma_msize {
/* Bitfields in CFG */
/* Bitfields in CFG */
#define DW_CFG_DMA_EN (1 << 0)
#define DW_CFG_DMA_EN (1 << 0)
/* iDMA 32-bit support */
/* Bitfields in CTL_HI */
#define IDMA32C_CTLH_BLOCK_TS_MASK GENMASK(16, 0)
#define IDMA32C_CTLH_BLOCK_TS(x) ((x) & IDMA32C_CTLH_BLOCK_TS_MASK)
#define IDMA32C_CTLH_DONE (1 << 17)
/* Bitfields in CFG_LO */
#define IDMA32C_CFGL_DST_BURST_ALIGN (1 << 0)
/* dst burst align */
#define IDMA32C_CFGL_SRC_BURST_ALIGN (1 << 1)
/* src burst align */
#define IDMA32C_CFGL_CH_DRAIN (1 << 10)
/* drain FIFO */
#define IDMA32C_CFGL_DST_OPT_BL (1 << 20)
/* optimize dst burst length */
#define IDMA32C_CFGL_SRC_OPT_BL (1 << 21)
/* optimize src burst length */
/* Bitfields in CFG_HI */
#define IDMA32C_CFGH_SRC_PER(x) ((x) << 0)
#define IDMA32C_CFGH_DST_PER(x) ((x) << 4)
#define IDMA32C_CFGH_RD_ISSUE_THD(x) ((x) << 8)
#define IDMA32C_CFGH_RW_ISSUE_THD(x) ((x) << 18)
#define IDMA32C_CFGH_SRC_PER_EXT(x) ((x) << 28)
/* src peripheral extension */
#define IDMA32C_CFGH_DST_PER_EXT(x) ((x) << 30)
/* dst peripheral extension */
/* Bitfields in FIFO_PARTITION */
#define IDMA32C_FP_PSIZE_CH0(x) ((x) << 0)
#define IDMA32C_FP_PSIZE_CH1(x) ((x) << 13)
#define IDMA32C_FP_UPDATE (1 << 26)
enum
dw_dmac_flags
{
enum
dw_dmac_flags
{
DW_DMA_IS_CYCLIC
=
0
,
DW_DMA_IS_CYCLIC
=
0
,
DW_DMA_IS_SOFT_LLP
=
1
,
DW_DMA_IS_SOFT_LLP
=
1
,
...
@@ -270,6 +313,7 @@ static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
...
@@ -270,6 +313,7 @@ static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
struct
dw_dma
{
struct
dw_dma
{
struct
dma_device
dma
;
struct
dma_device
dma
;
char
name
[
20
];
void
__iomem
*
regs
;
void
__iomem
*
regs
;
struct
dma_pool
*
desc_pool
;
struct
dma_pool
*
desc_pool
;
struct
tasklet_struct
tasklet
;
struct
tasklet_struct
tasklet
;
...
@@ -293,6 +337,11 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
...
@@ -293,6 +337,11 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
#define dma_writel(dw, name, val) \
#define dma_writel(dw, name, val) \
dma_writel_native((val), &(__dw_regs(dw)->name))
dma_writel_native((val), &(__dw_regs(dw)->name))
#define idma32_readq(dw, name) \
hi_lo_readq(&(__dw_regs(dw)->name))
#define idma32_writeq(dw, name, val) \
hi_lo_writeq((val), &(__dw_regs(dw)->name))
#define channel_set_bit(dw, reg, mask) \
#define channel_set_bit(dw, reg, mask) \
dma_writel(dw, reg, ((mask) << 8) | (mask))
dma_writel(dw, reg, ((mask) << 8) | (mask))
#define channel_clear_bit(dw, reg, mask) \
#define channel_clear_bit(dw, reg, mask) \
...
...
include/linux/dma/dw.h
浏览文件 @
e4e48c47
...
@@ -23,6 +23,7 @@ struct dw_dma;
...
@@ -23,6 +23,7 @@ struct dw_dma;
/**
/**
* struct dw_dma_chip - representation of DesignWare DMA controller hardware
* struct dw_dma_chip - representation of DesignWare DMA controller hardware
* @dev: struct device of the DMA controller
* @dev: struct device of the DMA controller
* @id: instance ID
* @irq: irq line
* @irq: irq line
* @regs: memory mapped I/O space
* @regs: memory mapped I/O space
* @clk: hclk clock
* @clk: hclk clock
...
@@ -31,6 +32,7 @@ struct dw_dma;
...
@@ -31,6 +32,7 @@ struct dw_dma;
*/
*/
struct
dw_dma_chip
{
struct
dw_dma_chip
{
struct
device
*
dev
;
struct
device
*
dev
;
int
id
;
int
irq
;
int
irq
;
void
__iomem
*
regs
;
void
__iomem
*
regs
;
struct
clk
*
clk
;
struct
clk
*
clk
;
...
...
include/linux/platform_data/dma-dw.h
浏览文件 @
e4e48c47
...
@@ -41,6 +41,7 @@ struct dw_dma_slave {
...
@@ -41,6 +41,7 @@ struct dw_dma_slave {
* @is_private: The device channels should be marked as private and not for
* @is_private: The device channels should be marked as private and not for
* by the general purpose DMA channel allocator.
* by the general purpose DMA channel allocator.
* @is_memcpy: The device channels do support memory-to-memory transfers.
* @is_memcpy: The device channels do support memory-to-memory transfers.
* @is_idma32: The type of the DMA controller is iDMA32
* @chan_allocation_order: Allocate channels starting from 0 or 7
* @chan_allocation_order: Allocate channels starting from 0 or 7
* @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0.
* @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0.
* @block_size: Maximum block size supported by the controller
* @block_size: Maximum block size supported by the controller
...
@@ -53,6 +54,7 @@ struct dw_dma_platform_data {
...
@@ -53,6 +54,7 @@ struct dw_dma_platform_data {
unsigned
int
nr_channels
;
unsigned
int
nr_channels
;
bool
is_private
;
bool
is_private
;
bool
is_memcpy
;
bool
is_memcpy
;
bool
is_idma32
;
#define CHAN_ALLOCATION_ASCENDING 0
/* zero to seven */
#define CHAN_ALLOCATION_ASCENDING 0
/* zero to seven */
#define CHAN_ALLOCATION_DESCENDING 1
/* seven to zero */
#define CHAN_ALLOCATION_DESCENDING 1
/* seven to zero */
unsigned
char
chan_allocation_order
;
unsigned
char
chan_allocation_order
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录