Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
bfe645ad
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看板
提交
bfe645ad
编写于
17年前
作者:
A
Arve Hjønnevåg
提交者:
Russell King
17年前
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[ARM] msm: dma support for MSM7X00A
Signed-off-by:
N
Brian Swetland
<
swetland@google.com
>
上级
9e73c84c
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
365 addition
and
1 deletion
+365
-1
arch/arm/mach-msm/Makefile
arch/arm/mach-msm/Makefile
+1
-1
arch/arm/mach-msm/dma.c
arch/arm/mach-msm/dma.c
+214
-0
include/asm-arm/arch-msm/dma.h
include/asm-arm/arch-msm/dma.h
+150
-0
未找到文件。
arch/arm/mach-msm/Makefile
浏览文件 @
bfe645ad
obj-y
+=
io.o idle.o irq.o timer.o
obj-y
+=
io.o idle.o irq.o timer.o
dma.o
# Common code for board init
obj-y
+=
common.o
...
...
This diff is collapsed.
Click to expand it.
arch/arm/mach-msm/dma.c
0 → 100644
浏览文件 @
bfe645ad
/* linux/arch/arm/mach-msm/dma.c
*
* Copyright (C) 2007 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
*/
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/arch/dma.h>
#define MSM_DMOV_CHANNEL_COUNT 16
enum
{
MSM_DMOV_PRINT_ERRORS
=
1
,
MSM_DMOV_PRINT_IO
=
2
,
MSM_DMOV_PRINT_FLOW
=
4
};
static
DEFINE_SPINLOCK
(
msm_dmov_lock
);
static
struct
msm_dmov_cmd
active_command
;
static
struct
list_head
ready_commands
[
MSM_DMOV_CHANNEL_COUNT
];
static
struct
list_head
active_commands
[
MSM_DMOV_CHANNEL_COUNT
];
unsigned
int
msm_dmov_print_mask
=
MSM_DMOV_PRINT_ERRORS
;
#define MSM_DMOV_DPRINTF(mask, format, args...) \
do { \
if ((mask) & msm_dmov_print_mask) \
printk(KERN_ERR format, args); \
} while (0)
#define PRINT_ERROR(format, args...) \
MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_ERRORS, format, args);
#define PRINT_IO(format, args...) \
MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_IO, format, args);
#define PRINT_FLOW(format, args...) \
MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_FLOW, format, args);
void
msm_dmov_enqueue_cmd
(
unsigned
id
,
struct
msm_dmov_cmd
*
cmd
)
{
unsigned
long
irq_flags
;
unsigned
int
status
;
spin_lock_irqsave
(
&
msm_dmov_lock
,
irq_flags
);
status
=
readl
(
DMOV_STATUS
(
id
));
if
(
list_empty
(
&
ready_commands
[
id
])
&&
(
status
&
DMOV_STATUS_CMD_PTR_RDY
))
{
#if 0
if (list_empty(&active_commands[id])) {
PRINT_FLOW("msm_dmov_enqueue_cmd(%d), enable interrupt\n", id);
writel(DMOV_CONFIG_IRQ_EN, DMOV_CONFIG(id));
}
#endif
PRINT_IO
(
"msm_dmov_enqueue_cmd(%d), start command, status %x
\n
"
,
id
,
status
);
list_add_tail
(
&
cmd
->
list
,
&
active_commands
[
id
]);
writel
(
cmd
->
cmdptr
,
DMOV_CMD_PTR
(
id
));
}
else
{
if
(
list_empty
(
&
active_commands
[
id
]))
PRINT_ERROR
(
"msm_dmov_enqueue_cmd(%d), error datamover stalled, status %x
\n
"
,
id
,
status
);
PRINT_IO
(
"msm_dmov_enqueue_cmd(%d), enqueue command, status %x
\n
"
,
id
,
status
);
list_add_tail
(
&
cmd
->
list
,
&
ready_commands
[
id
]);
}
spin_unlock_irqrestore
(
&
msm_dmov_lock
,
irq_flags
);
}
struct
msm_dmov_exec_cmdptr_cmd
{
struct
msm_dmov_cmd
dmov_cmd
;
struct
completion
complete
;
unsigned
id
;
unsigned
int
result
;
unsigned
int
flush
[
6
];
};
static
void
dmov_exec_cmdptr_complete_func
(
struct
msm_dmov_cmd
*
_cmd
,
unsigned
int
result
)
{
struct
msm_dmov_exec_cmdptr_cmd
*
cmd
=
container_of
(
_cmd
,
struct
msm_dmov_exec_cmdptr_cmd
,
dmov_cmd
);
cmd
->
result
=
result
;
if
(
result
!=
0x80000002
)
{
cmd
->
flush
[
0
]
=
readl
(
DMOV_FLUSH0
(
cmd
->
id
));
cmd
->
flush
[
1
]
=
readl
(
DMOV_FLUSH1
(
cmd
->
id
));
cmd
->
flush
[
2
]
=
readl
(
DMOV_FLUSH2
(
cmd
->
id
));
cmd
->
flush
[
3
]
=
readl
(
DMOV_FLUSH3
(
cmd
->
id
));
cmd
->
flush
[
4
]
=
readl
(
DMOV_FLUSH4
(
cmd
->
id
));
cmd
->
flush
[
5
]
=
readl
(
DMOV_FLUSH5
(
cmd
->
id
));
}
complete
(
&
cmd
->
complete
);
}
int
msm_dmov_exec_cmd
(
unsigned
id
,
unsigned
int
cmdptr
)
{
struct
msm_dmov_exec_cmdptr_cmd
cmd
;
PRINT_FLOW
(
"dmov_exec_cmdptr(%d, %x)
\n
"
,
id
,
cmdptr
);
cmd
.
dmov_cmd
.
cmdptr
=
cmdptr
;
cmd
.
dmov_cmd
.
complete_func
=
dmov_exec_cmdptr_complete_func
;
cmd
.
id
=
id
;
init_completion
(
&
cmd
.
complete
);
msm_dmov_enqueue_cmd
(
id
,
&
cmd
.
dmov_cmd
);
wait_for_completion
(
&
cmd
.
complete
);
if
(
cmd
.
result
!=
0x80000002
)
{
PRINT_ERROR
(
"dmov_exec_cmdptr(%d): ERROR, result: %x
\n
"
,
id
,
cmd
.
result
);
PRINT_ERROR
(
"dmov_exec_cmdptr(%d): flush: %x %x %x %x
\n
"
,
id
,
cmd
.
flush
[
0
],
cmd
.
flush
[
1
],
cmd
.
flush
[
2
],
cmd
.
flush
[
3
]);
return
-
EIO
;
}
PRINT_FLOW
(
"dmov_exec_cmdptr(%d, %x) done
\n
"
,
id
,
cmdptr
);
return
0
;
}
static
irqreturn_t
msm_datamover_irq_handler
(
int
irq
,
void
*
dev_id
)
{
unsigned
int
int_status
,
mask
,
id
;
unsigned
long
irq_flags
;
unsigned
int
ch_status
;
unsigned
int
ch_result
;
struct
msm_dmov_cmd
*
cmd
;
spin_lock_irqsave
(
&
msm_dmov_lock
,
irq_flags
);
int_status
=
readl
(
DMOV_ISR
);
/* read and clear interrupt */
PRINT_FLOW
(
"msm_datamover_irq_handler: DMOV_ISR %x
\n
"
,
int_status
);
while
(
int_status
)
{
mask
=
int_status
&
-
int_status
;
id
=
fls
(
mask
)
-
1
;
PRINT_FLOW
(
"msm_datamover_irq_handler %08x %08x id %d
\n
"
,
int_status
,
mask
,
id
);
int_status
&=
~
mask
;
ch_status
=
readl
(
DMOV_STATUS
(
id
));
if
(
!
(
ch_status
&
DMOV_STATUS_RSLT_VALID
))
{
PRINT_FLOW
(
"msm_datamover_irq_handler id %d, result not valid %x
\n
"
,
id
,
ch_status
);
continue
;
}
do
{
ch_result
=
readl
(
DMOV_RSLT
(
id
));
if
(
list_empty
(
&
active_commands
[
id
]))
{
PRINT_ERROR
(
"msm_datamover_irq_handler id %d, got result "
"with no active command, status %x, result %x
\n
"
,
id
,
ch_status
,
ch_result
);
cmd
=
NULL
;
}
else
cmd
=
list_entry
(
active_commands
[
id
].
next
,
typeof
(
*
cmd
),
list
);
PRINT_FLOW
(
"msm_datamover_irq_handler id %d, status %x, result %x
\n
"
,
id
,
ch_status
,
ch_result
);
if
(
ch_result
&
DMOV_RSLT_DONE
)
{
PRINT_FLOW
(
"msm_datamover_irq_handler id %d, status %x
\n
"
,
id
,
ch_status
);
PRINT_IO
(
"msm_datamover_irq_handler id %d, got result "
"for %p, result %x
\n
"
,
id
,
cmd
,
ch_result
);
if
(
cmd
)
{
list_del
(
&
cmd
->
list
);
cmd
->
complete_func
(
cmd
,
ch_result
);
}
}
if
(
ch_result
&
DMOV_RSLT_FLUSH
)
{
unsigned
int
flush0
=
readl
(
DMOV_FLUSH0
(
id
));
PRINT_FLOW
(
"msm_datamover_irq_handler id %d, status %x
\n
"
,
id
,
ch_status
);
PRINT_FLOW
(
"msm_datamover_irq_handler id %d, flush, result %x, flush0 %x
\n
"
,
id
,
ch_result
,
flush0
);
if
(
cmd
)
{
list_del
(
&
cmd
->
list
);
cmd
->
complete_func
(
cmd
,
ch_result
);
}
}
if
(
ch_result
&
DMOV_RSLT_ERROR
)
{
unsigned
int
flush0
=
readl
(
DMOV_FLUSH0
(
id
));
PRINT_ERROR
(
"msm_datamover_irq_handler id %d, status %x
\n
"
,
id
,
ch_status
);
PRINT_ERROR
(
"msm_datamover_irq_handler id %d, error, result %x, flush0 %x
\n
"
,
id
,
ch_result
,
flush0
);
if
(
cmd
)
{
list_del
(
&
cmd
->
list
);
cmd
->
complete_func
(
cmd
,
ch_result
);
}
/* this does not seem to work, once we get an error */
/* the datamover will no longer accept commands */
writel
(
0
,
DMOV_FLUSH0
(
id
));
}
ch_status
=
readl
(
DMOV_STATUS
(
id
));
PRINT_FLOW
(
"msm_datamover_irq_handler id %d, status %x
\n
"
,
id
,
ch_status
);
if
((
ch_status
&
DMOV_STATUS_CMD_PTR_RDY
)
&&
!
list_empty
(
&
ready_commands
[
id
]))
{
cmd
=
list_entry
(
ready_commands
[
id
].
next
,
typeof
(
*
cmd
),
list
);
list_del
(
&
cmd
->
list
);
list_add_tail
(
&
cmd
->
list
,
&
active_commands
[
id
]);
PRINT_FLOW
(
"msm_datamover_irq_handler id %d, start command
\n
"
,
id
);
writel
(
cmd
->
cmdptr
,
DMOV_CMD_PTR
(
id
));
}
}
while
(
ch_status
&
DMOV_STATUS_RSLT_VALID
);
PRINT_FLOW
(
"msm_datamover_irq_handler id %d, status %x
\n
"
,
id
,
ch_status
);
}
spin_unlock_irqrestore
(
&
msm_dmov_lock
,
irq_flags
);
return
IRQ_HANDLED
;
}
static
int
__init
msm_init_datamover
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
MSM_DMOV_CHANNEL_COUNT
;
i
++
)
{
INIT_LIST_HEAD
(
&
ready_commands
[
i
]);
INIT_LIST_HEAD
(
&
active_commands
[
i
]);
writel
(
DMOV_CONFIG_IRQ_EN
|
DMOV_CONFIG_FORCE_TOP_PTR_RSLT
|
DMOV_CONFIG_FORCE_FLUSH_RSLT
,
DMOV_CONFIG
(
i
));
}
return
request_irq
(
INT_ADM_AARM
,
msm_datamover_irq_handler
,
0
,
"msmdatamover"
,
NULL
);
}
arch_initcall
(
msm_init_datamover
);
This diff is collapsed.
Click to expand it.
include/asm-arm/arch-msm/dma.h
浏览文件 @
bfe645ad
/* linux/include/asm-arm/arch-msm/dma.h
*
* Copyright (C) 2007 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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 __ASM_ARCH_MSM_DMA_H
#include <linux/list.h>
#include <asm/arch/msm_iomap.h>
struct
msm_dmov_cmd
{
struct
list_head
list
;
unsigned
int
cmdptr
;
void
(
*
complete_func
)(
struct
msm_dmov_cmd
*
cmd
,
unsigned
int
result
);
/* void (*user_result_func)(struct msm_dmov_cmd *cmd); */
};
void
msm_dmov_enqueue_cmd
(
unsigned
id
,
struct
msm_dmov_cmd
*
cmd
);
void
msm_dmov_stop_cmd
(
unsigned
id
,
struct
msm_dmov_cmd
*
cmd
);
int
msm_dmov_exec_cmd
(
unsigned
id
,
unsigned
int
cmdptr
);
/* int msm_dmov_exec_cmd_etc(unsigned id, unsigned int cmdptr, int timeout, int interruptible); */
#define DMOV_SD0(off, ch) (MSM_DMOV_BASE + 0x0000 + (off) + ((ch) << 2))
#define DMOV_SD1(off, ch) (MSM_DMOV_BASE + 0x0400 + (off) + ((ch) << 2))
#define DMOV_SD2(off, ch) (MSM_DMOV_BASE + 0x0800 + (off) + ((ch) << 2))
#define DMOV_SD3(off, ch) (MSM_DMOV_BASE + 0x0C00 + (off) + ((ch) << 2))
/* only security domain 3 is available to the ARM11
* SD0 -> mARM trusted, SD1 -> mARM nontrusted, SD2 -> aDSP, SD3 -> aARM
*/
#define DMOV_CMD_PTR(ch) DMOV_SD3(0x000, ch)
#define DMOV_CMD_LIST (0 << 29)
/* does not work */
#define DMOV_CMD_PTR_LIST (1 << 29)
/* works */
#define DMOV_CMD_INPUT_CFG (2 << 29)
/* untested */
#define DMOV_CMD_OUTPUT_CFG (3 << 29)
/* untested */
#define DMOV_CMD_ADDR(addr) ((addr) >> 3)
#define DMOV_RSLT(ch) DMOV_SD3(0x040, ch)
#define DMOV_RSLT_VALID (1 << 31)
/* 0 == host has empties result fifo */
#define DMOV_RSLT_ERROR (1 << 3)
#define DMOV_RSLT_FLUSH (1 << 2)
#define DMOV_RSLT_DONE (1 << 1)
/* top pointer done */
#define DMOV_RSLT_USER (1 << 0)
/* command with FR force result */
#define DMOV_FLUSH0(ch) DMOV_SD3(0x080, ch)
#define DMOV_FLUSH1(ch) DMOV_SD3(0x0C0, ch)
#define DMOV_FLUSH2(ch) DMOV_SD3(0x100, ch)
#define DMOV_FLUSH3(ch) DMOV_SD3(0x140, ch)
#define DMOV_FLUSH4(ch) DMOV_SD3(0x180, ch)
#define DMOV_FLUSH5(ch) DMOV_SD3(0x1C0, ch)
#define DMOV_STATUS(ch) DMOV_SD3(0x200, ch)
#define DMOV_STATUS_RSLT_COUNT(n) (((n) >> 29))
#define DMOV_STATUS_CMD_COUNT(n) (((n) >> 27) & 3)
#define DMOV_STATUS_RSLT_VALID (1 << 1)
#define DMOV_STATUS_CMD_PTR_RDY (1 << 0)
#define DMOV_ISR DMOV_SD3(0x380, 0)
#define DMOV_CONFIG(ch) DMOV_SD3(0x300, ch)
#define DMOV_CONFIG_FORCE_TOP_PTR_RSLT (1 << 2)
#define DMOV_CONFIG_FORCE_FLUSH_RSLT (1 << 1)
#define DMOV_CONFIG_IRQ_EN (1 << 0)
/* channel assignments */
#define DMOV_NAND_CHAN 7
#define DMOV_NAND_CRCI_CMD 5
#define DMOV_NAND_CRCI_DATA 4
#define DMOV_SDC1_CHAN 8
#define DMOV_SDC1_CRCI 6
#define DMOV_SDC2_CHAN 8
#define DMOV_SDC2_CRCI 7
#define DMOV_TSIF_CHAN 10
#define DMOV_TSIF_CRCI 10
#define DMOV_USB_CHAN 11
/* no client rate control ifc (eg, ram) */
#define DMOV_NONE_CRCI 0
/* If the CMD_PTR register has CMD_PTR_LIST selected, the data mover
* is going to walk a list of 32bit pointers as described below. Each
* pointer points to a *array* of dmov_s, etc structs. The last pointer
* in the list is marked with CMD_PTR_LP. The last struct in each array
* is marked with CMD_LC (see below).
*/
#define CMD_PTR_ADDR(addr) ((addr) >> 3)
#define CMD_PTR_LP (1 << 31)
/* last pointer */
#define CMD_PTR_PT (3 << 29)
/* ? */
/* Single Item Mode */
typedef
struct
{
unsigned
cmd
;
unsigned
src
;
unsigned
dst
;
unsigned
len
;
}
dmov_s
;
/* Scatter/Gather Mode */
typedef
struct
{
unsigned
cmd
;
unsigned
src_dscr
;
unsigned
dst_dscr
;
unsigned
_reserved
;
}
dmov_sg
;
/* bits for the cmd field of the above structures */
#define CMD_LC (1 << 31)
/* last command */
#define CMD_FR (1 << 22)
/* force result -- does not work? */
#define CMD_OCU (1 << 21)
/* other channel unblock */
#define CMD_OCB (1 << 20)
/* other channel block */
#define CMD_TCB (1 << 19)
/* ? */
#define CMD_DAH (1 << 18)
/* destination address hold -- does not work?*/
#define CMD_SAH (1 << 17)
/* source address hold -- does not work? */
#define CMD_MODE_SINGLE (0 << 0)
/* dmov_s structure used */
#define CMD_MODE_SG (1 << 0)
/* untested */
#define CMD_MODE_IND_SG (2 << 0)
/* untested */
#define CMD_MODE_BOX (3 << 0)
/* untested */
#define CMD_DST_SWAP_BYTES (1 << 14)
/* exchange each byte n with byte n+1 */
#define CMD_DST_SWAP_SHORTS (1 << 15)
/* exchange each short n with short n+1 */
#define CMD_DST_SWAP_WORDS (1 << 16)
/* exchange each word n with word n+1 */
#define CMD_SRC_SWAP_BYTES (1 << 11)
/* exchange each byte n with byte n+1 */
#define CMD_SRC_SWAP_SHORTS (1 << 12)
/* exchange each short n with short n+1 */
#define CMD_SRC_SWAP_WORDS (1 << 13)
/* exchange each word n with word n+1 */
#define CMD_DST_CRCI(n) (((n) & 15) << 7)
#define CMD_SRC_CRCI(n) (((n) & 15) << 3)
#endif
This diff is collapsed.
Click to expand it.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录
新手
引导
客服
返回
顶部