Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
b3ddf280
Commit
b3ddf280
authored
Jul 27, 2005
by
Toshiro Kobayashi
Committed by
Tony Lindgren
Jul 27, 2005
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] ARM: OMAP: DSP Gateway v3.3
This is DSP Gateway v3.3 patch.
parent
76330285
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1603 additions
and
679 deletions
+1603
-679
arch/arm/plat-omap/dsp/dsp.h
arch/arm/plat-omap/dsp/dsp.h
+69
-27
arch/arm/plat-omap/dsp/dsp_common.c
arch/arm/plat-omap/dsp/dsp_common.c
+331
-50
arch/arm/plat-omap/dsp/dsp_common.h
arch/arm/plat-omap/dsp/dsp_common.h
+30
-15
arch/arm/plat-omap/dsp/dsp_core.c
arch/arm/plat-omap/dsp/dsp_core.c
+105
-50
arch/arm/plat-omap/dsp/dsp_ctl.c
arch/arm/plat-omap/dsp/dsp_ctl.c
+225
-129
arch/arm/plat-omap/dsp/dsp_ctl_core.c
arch/arm/plat-omap/dsp/dsp_ctl_core.c
+5
-13
arch/arm/plat-omap/dsp/dsp_mem.c
arch/arm/plat-omap/dsp/dsp_mem.c
+286
-132
arch/arm/plat-omap/dsp/error.c
arch/arm/plat-omap/dsp/error.c
+15
-4
arch/arm/plat-omap/dsp/fifo.h
arch/arm/plat-omap/dsp/fifo.h
+1
-1
arch/arm/plat-omap/dsp/hardware_dsp.h
arch/arm/plat-omap/dsp/hardware_dsp.h
+15
-1
arch/arm/plat-omap/dsp/ipbuf.c
arch/arm/plat-omap/dsp/ipbuf.c
+87
-31
arch/arm/plat-omap/dsp/ipbuf.h
arch/arm/plat-omap/dsp/ipbuf.h
+6
-5
arch/arm/plat-omap/dsp/mblog.c
arch/arm/plat-omap/dsp/mblog.c
+9
-8
arch/arm/plat-omap/dsp/proclist.h
arch/arm/plat-omap/dsp/proclist.h
+1
-1
arch/arm/plat-omap/dsp/task.c
arch/arm/plat-omap/dsp/task.c
+389
-200
arch/arm/plat-omap/dsp/taskwatch.c
arch/arm/plat-omap/dsp/taskwatch.c
+7
-2
arch/arm/plat-omap/dsp/uaccess_dsp.S
arch/arm/plat-omap/dsp/uaccess_dsp.S
+1
-1
arch/arm/plat-omap/dsp/uaccess_dsp.h
arch/arm/plat-omap/dsp/uaccess_dsp.h
+1
-1
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/mcbsp.c
+2
-1
include/asm-arm/arch-omap/dsp.h
include/asm-arm/arch-omap/dsp.h
+13
-5
include/asm-arm/arch-omap/dsp_common.h
include/asm-arm/arch-omap/dsp_common.h
+5
-2
No files found.
arch/arm/plat-omap/dsp/dsp.h
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2005/0
1/21: DSP Gateway version 3.2
* 2005/0
6/09: DSP Gateway version 3.3
*/
#include "hardware_dsp.h"
...
...
@@ -31,6 +31,7 @@
#ifdef OLD_BINARY_SUPPORT
#define MBREV_3_0 0x0017
#define MBREV_3_2 0x0018
#endif
#define DSP_INIT_PAGE 0xfff000
...
...
@@ -38,6 +39,22 @@
#define IDLEPG_BASE 0xfffe00
#define IDLEPG_SIZE 0x100
/* timeout value for DSP response */
#define DSP_TIMEOUT (10 * HZ)
enum
dsp_mem_type_e
{
MEM_TYPE_CROSSING
=
-
1
,
MEM_TYPE_NONE
=
0
,
MEM_TYPE_DARAM
,
MEM_TYPE_SARAM
,
MEM_TYPE_EXTERN
,
};
enum
arm_dsp_dir
{
DIR_A2D
,
DIR_D2A
,
};
/*
* INT_D2A_MB value definition
* INT_DSP_MAILBOX1: use Mailbox 1 (INT 10) for DSP->ARM mailbox
...
...
@@ -49,8 +66,22 @@
#define TASKDEV_MAX 254
#define MKLONG(uw,lw) (((unsigned long)(uw)) << 16 | (lw))
#define MKVIRT(uw,lw) dspword_to_virt(MKLONG((uw), (lw)));
#define MBCMD(nm) OMAP_DSP_MBCMD_##nm
struct
sync_seq
{
unsigned
short
da_dsp
;
unsigned
short
da_arm
;
unsigned
short
ad_dsp
;
unsigned
short
ad_arm
;
};
struct
mem_sync_struct
{
struct
sync_seq
*
DARAM
;
struct
sync_seq
*
SARAM
;
struct
sync_seq
*
SDRAM
;
};
/* struct mbcmd and struct mbcmd_hw must be compatible */
struct
mbcmd
{
unsigned
short
cmd_l
:
8
;
...
...
@@ -79,26 +110,32 @@ struct mb_exarg {
extern
void
dsp_mb_start
(
void
);
extern
void
dsp_mb_stop
(
void
);
extern
void
dsp_mb_config
(
void
*
sync_seq_adr
);
extern
int
dsp_mb_config
(
void
*
p
);
extern
int
sync_with_dsp
(
unsigned
short
*
syncwd
,
unsigned
short
tid
,
int
try_cnt
);
extern
int
__mbsend
(
struct
mbcmd
*
mb
);
extern
int
__dsp_mbsend
(
struct
mbcmd
*
mb
,
struct
mb_exarg
*
arg
,
int
recovery_flag
);
#define dsp_mbsend(mb) __dsp_mbsend(mb, NULL, 0)
#define dsp_mbsend_recovery(mb) __dsp_mbsend(mb, NULL, 1)
#define dsp_mbsend_exarg(mb, arg) __dsp_mbsend(mb, arg, 0)
extern
int
__dsp_mbsend_and_wait
(
struct
mbcmd
*
mb
,
struct
mb_exarg
*
arg
,
wait_queue_head_t
*
q
);
#define dsp_mbsend_and_wait(mb, q) \
__dsp_mbsend_and_wait(mb, NULL, q)
#define dsp_mbsend_and_wait_exarg(mb, arg, q) \
__dsp_mbsend_and_wait(mb, arg, q)
extern
int
__mbcmd_send
(
struct
mbcmd
*
mb
);
extern
int
__dsp_mbcmd_send
(
struct
mbcmd
*
mb
,
struct
mb_exarg
*
arg
,
int
recovery_flag
);
#define dsp_mbcmd_send(mb) __dsp_mbcmd_send(mb, NULL, 0)
#define dsp_mbcmd_send_exarg(mb, arg) __dsp_mbcmd_send(mb, arg, 0)
extern
int
__dsp_mbcmd_send_and_wait
(
struct
mbcmd
*
mb
,
struct
mb_exarg
*
arg
,
wait_queue_head_t
*
q
);
#define dsp_mbcmd_send_and_wait(mb, q) \
__dsp_mbcmd_send_and_wait(mb, NULL, q)
#define dsp_mbcmd_send_and_wait_exarg(mb, arg, q) \
__dsp_mbcmd_send_and_wait(mb, arg, q)
int
__dsp_mbsend
(
unsigned
char
cmdh
,
unsigned
char
cmdl
,
unsigned
short
data
,
int
recovery_flag
);
#define dsp_mbsend(cmdh, cmdl, data) \
__dsp_mbsend(cmdh, cmdl, data, 0)
#define dsp_mbsend_recovery(cmdh, cmdl, data) \
__dsp_mbsend(cmdh, cmdl, data, 1)
extern
void
ipbuf_start
(
void
);
extern
void
ipbuf_stop
(
void
);
extern
int
ipbuf_config
(
unsigned
short
ln
,
unsigned
short
lsz
,
unsigned
long
adr
);
extern
int
ipbuf_config
(
unsigned
short
ln
,
unsigned
short
lsz
,
void
*
base
);
extern
int
ipbuf_sys_config
(
void
*
p
,
enum
arm_dsp_dir
dir
);
extern
int
ipbuf_p_validate
(
void
*
p
,
enum
arm_dsp_dir
dir
);
extern
unsigned
short
get_free_ipbuf
(
unsigned
char
tid
);
extern
void
unuse_ipbuf_nowait
(
unsigned
short
bid
);
extern
void
unuse_ipbuf
(
unsigned
short
bid
);
...
...
@@ -110,6 +147,8 @@ extern void balance_ipbuf(void);
(ipbuf_pvt)->s = OMAP_DSP_TID_FREE; \
} while(0)
extern
int
mbx_revision
;
extern
int
dsp_is_ready
(
void
);
extern
int
dspuncfg
(
void
);
extern
void
dsp_runlevel
(
unsigned
char
level
);
...
...
@@ -125,16 +164,24 @@ extern int dsp_rmdev(char *name);
extern
int
dsp_tadd
(
unsigned
char
minor
,
unsigned
long
adr
);
extern
int
dsp_tdel
(
unsigned
char
minor
);
extern
int
dsp_tkill
(
unsigned
char
minor
);
extern
long
taskdev_state
(
unsigned
char
minor
);
extern
long
taskdev_state_stale
(
unsigned
char
minor
);
extern
int
dsp_dbg_config
(
short
*
buf
,
unsigned
short
sz
,
unsigned
short
lsz
);
extern
void
dsp_dbg_stop
(
void
);
extern
int
ipbuf_is_held
(
unsigned
char
tid
,
unsigned
short
bid
);
extern
void
dsp_mem_sync_inc
(
void
);
extern
int
dsp_mem_sync_config
(
struct
mem_sync_struct
*
sync
);
extern
enum
dsp_mem_type_e
dsp_mem_type
(
void
*
vadr
,
size_t
len
);
extern
int
dsp_address_validate
(
void
*
p
,
size_t
len
,
char
*
fmt
,
...);
extern
int
dsp_mem_enable
(
void
*
adr
);
extern
int
dsp_mem_disable
(
void
*
adr
);
extern
int
__dsp_mem_enable
(
void
*
adr
);
extern
int
__dsp_mem_disable
(
void
*
adr
);
extern
void
dsp_mem_disable
(
void
*
adr
);
extern
void
dsp_mem_usecount_clear
(
void
);
extern
void
exmap_use
(
void
*
vadr
,
size_t
len
);
extern
void
exmap_unuse
(
void
*
vadr
,
size_t
len
);
extern
unsigned
long
dsp_virt_to_phys
(
void
*
vadr
,
size_t
*
len
);
extern
void
dsp_mem_start
(
void
);
extern
void
dsp_mem_stop
(
void
);
extern
void
dsp_twch_start
(
void
);
extern
void
dsp_twch_stop
(
void
);
...
...
@@ -165,14 +212,9 @@ extern const struct cmdinfo *cmdinfo[];
#define cmd_name(mb) (cmdinfo[(mb).cmd_h]->name)
extern
char
*
subcmd_name
(
struct
mbcmd
*
mb
);
enum
mblog_dir
{
MBLOG_DIR_AD
,
MBLOG_DIR_DA
,
};
extern
void
mblog_add
(
struct
mbcmd
*
mb
,
enum
mblog_dir
dir
);
extern
void
mblog_add
(
struct
mbcmd
*
mb
,
enum
arm_dsp_dir
dir
);
#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
extern
void
mblog_printcmd
(
struct
mbcmd
*
mb
,
enum
mblog
_dir
dir
);
extern
void
mblog_printcmd
(
struct
mbcmd
*
mb
,
enum
arm_dsp
_dir
dir
);
#else
/* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
#define mblog_printcmd(mb, dir) do {} while(0)
#endif
/* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
...
...
arch/arm/plat-omap/dsp/dsp_common.c
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 200
4/11/19: DSP Gateway version 3.2
* 200
5/06/13: DSP Gateway version 3.3
*/
#include <linux/module.h>
...
...
@@ -40,14 +40,28 @@
struct
clk
*
dsp_ck_handle
;
struct
clk
*
api_ck_handle
;
unsigned
long
dspmem_base
,
dspmem_size
;
int
dsp_runstat
=
RUNSTAT_RESET
;
unsigned
short
dsp_icrmask
=
DSPREG_ICR_EMIF_IDLE_DOMAIN
|
DSPREG_ICR_DPLL_IDLE_DOMAIN
|
DSPREG_ICR_PER_IDLE_DOMAIN
|
DSPREG_ICR_CACHE_IDLE_DOMAIN
|
DSPREG_ICR_DMA_IDLE_DOMAIN
|
DSPREG_ICR_CPU_IDLE_DOMAIN
;
unsigned
long
dspmem_base
,
dspmem_size
,
daram_base
,
daram_size
,
saram_base
,
saram_size
;
struct
cpustat
{
struct
semaphore
sem
;
enum
e_cpustat
stat
;
enum
e_cpustat
req
;
unsigned
short
icrmask
;
struct
{
int
mpui
;
int
mem
;
int
mem_delayed
;
}
usecount
;
int
(
*
mem_req_cb
)(
void
);
void
(
*
mem_rel_cb
)(
void
);
};
struct
cpustat
cpustat
=
{
.
sem
=
__MUTEX_INITIALIZER
(
cpustat
.
sem
),
.
stat
=
CPUSTAT_RESET
,
.
icrmask
=
0xffff
,
};
int
dsp_set_rstvect
(
unsigned
long
adr
)
{
...
...
@@ -88,22 +102,59 @@ static void simple_load_code(unsigned char *src_c, unsigned short *dst, int len)
}
/* program size must be multiple of 2 */
#define IDLE_TEXT_SIZE 28
#define IDLE_TEXT(icr) { \
#define GBL_IDLE_TEXT_SIZE 52
#define GBL_IDLE_TEXT_INIT { \
/* SAM */
\
0x3c, 0x4a,
/* 0x3c4a: MOV 0x4, AR2 */
\
0xf4, 0x41, 0xfc, 0xff,
/* 0xf441fcff: AND 0xfcff, *AR2 */
\
/* disable WDT */
\
0x76, 0x34, 0x04, 0xb8,
/* 0x763404b8: mov AR3 0x3404 */
\
0xfb, 0x61, 0x00, 0xf5,
/* 0xfb6100f5: mov *AR3 0x00f5 */
\
0x9a,
/* 0x9a: port */
\
0xfb, 0x61, 0x00, 0xa0,
/* 0xfb6100a0: mov *AR3 0x00a0 */
\
0x9a,
/* 0x9a: port */
\
0x76, 0x34, 0x04, 0xb8,
/* 0x763404b8: MOV 0x3404, AR3 */
\
0xfb, 0x61, 0x00, 0xf5,
/* 0xfb6100f5: MOV 0x00f5, *AR3 */
\
0x9a,
/* 0x9a: PORT */
\
0xfb, 0x61, 0x00, 0xa0,
/* 0xfb6100a0: MOV 0x00a0, *AR3 */
\
0x9a,
/* 0x9a: PORT */
\
/* *IER0 = 0, *IER1 = 0 */
\
0x3c, 0x0b,
/* 0x3c0b: MOV 0x0, AR3 */
\
0xe6, 0x61, 0x00,
/* 0xe66100: MOV 0, *AR3 */
\
0x76, 0x00, 0x45, 0xb8,
/* 0x76004508: MOV 0x45, AR3 */
\
0xe6, 0x61, 0x00,
/* 0xe66100: MOV 0, *AR3 */
\
/* *ICR = 0xffff */
\
0x3c, 0x1b,
/* 0x3c1b: MOV 0x1, AR3 */
\
0xfb, 0x61, 0xff, 0xff,
/* 0xfb61ffff: MOV 0xffff, *AR3 */
\
0x9a,
/* 0x9a: PORT */
\
/* HOM */
\
0xf5, 0x41, 0x03, 0x00,
/* 0xf5410300: OR 0x0300, *AR2 */
\
/* idle and loop forever */
\
0x7a, 0x00, 0x00, 0x0c,
/* 0x7a00000c: IDLE */
\
0x4a, 0x7a,
/* 0x4a7a: B -6 (infinite loop) */
\
0x20, 0x20, 0x20,
/* 0x20: NOP */
\
}
/* program size must be multiple of 2 */
#define CPU_IDLE_TEXT_SIZE 48
#define CPU_IDLE_TEXT_INIT(icrh, icrl) { \
/* SAM */
\
0x3c, 0x4b,
/* 0x3c4b: MOV 0x4, AR3 */
\
0xf4, 0x61, 0xfc, 0xff,
/* 0xf461fcff: AND 0xfcff, *AR3 */
\
/* disable WDT */
\
0x76, 0x34, 0x04, 0xb8,
/* 0x763404b8: MOV 0x3404, AR3 */
\
0xfb, 0x61, 0x00, 0xf5,
/* 0xfb6100f5: MOV 0x00f5, *AR3 */
\
0x9a,
/* 0x9a: PORT */
\
0xfb, 0x61, 0x00, 0xa0,
/* 0xfb6100a0: MOV 0x00a0, *AR3 */
\
0x9a,
/* 0x9a: PORT */
\
/* *IER0 = 0, *IER1 = 0 */
\
0x3c, 0x0b,
/* 0x3c0b: MOV 0x0, AR3 */
\
0xe6, 0x61, 0x00,
/* 0xe66100: MOV 0, *AR3 */
\
0x76, 0x00, 0x45, 0xb8,
/* 0x76004508: MOV 0x45, AR3 */
\
0xe6, 0x61, 0x00,
/* 0xe66100: MOV 0, *AR3 */
\
/* set ICR = icr */
\
0x3c, 0x1b,
/* 0x3c1b:
mov
AR3 0x1 */
\
0x
e6, 0x61, (icr),
/* 0xe661**: mov
*AR3, icr */
\
0x9a,
/* 0x9a:
port
*/
\
0x3c, 0x1b,
/* 0x3c1b:
MOV
AR3 0x1 */
\
0x
fb, 0x61, (icrh), (icrl),
/* 0xfb61****: MOV
*AR3, icr */
\
0x9a,
/* 0x9a:
PORT
*/
\
/* idle and loop forever */
\
0x7a, 0x00, 0x00, 0x0c,
/* 0x7a00000c:
idle
*/
\
0x4a, 0x7a,
/* 0x4a7a:
b
-6 (infinite loop) */
\
0x20, 0x20
/* 0x20: nop */
\
0x7a, 0x00, 0x00, 0x0c,
/* 0x7a00000c:
IDLE
*/
\
0x4a, 0x7a,
/* 0x4a7a:
B
-6 (infinite loop) */
\
0x20, 0x20
, 0x20
/* 0x20: nop */
\
}
/*
...
...
@@ -115,38 +166,57 @@ static void simple_load_code(unsigned char *src_c, unsigned short *dst, int len)
*/
static
unsigned
long
idle_boot_base
=
DSP_BOOT_ADR_MPUI
;
void
dsp_idle
(
void
)
static
void
dsp_gbl_idle
(
void
)
{
unsigned
char
idle_text
[
GBL_IDLE_TEXT_SIZE
]
=
GBL_IDLE_TEXT_INIT
;
__dsp_reset
();
clk_use
(
api_ck_handle
);
#if 0
omap_writew(MPUI_DSP_BOOT_CONFIG_IDLE, MPUI_DSP_BOOT_CONFIG);
#endif
simple_load_code
(
idle_text
,
dspbyte_to_virt
(
idle_boot_base
),
GBL_IDLE_TEXT_SIZE
);
if
(
idle_boot_base
==
DSP_BOOT_ADR_MPUI
)
omap_writew
(
MPUI_DSP_BOOT_CONFIG_MPUI
,
MPUI_DSP_BOOT_CONFIG
);
else
dsp_set_rstvect
(
idle_boot_base
);
__dsp_run
();
udelay
(
100
);
/* to make things stable */
clk_unuse
(
api_ck_handle
);
}
static
void
dsp_cpu_idle
(
void
)
{
unsigned
char
icr
;
unsigned
short
icr_tmp
;
unsigned
char
icrh
,
icrl
;
disable_irq
(
INT_DSP_MMU
);
preempt_disable
();
__dsp_reset
();
clk_use
(
api_ck_handle
);
/*
* icr settings:
* DMA should not sleep for DARAM/SARAM access
* DPLL should not sleep
for DMA.
* DPLL should not sleep
while any other domain is active
*/
icr
=
dsp_icrmask
&
~
(
DSPREG_ICR_DMA_IDLE_DOMAIN
|
DSPREG_ICR_DPLL_IDLE_DOMAIN
)
&
0xff
;
icr_tmp
=
cpustat
.
icrmask
&
~
(
DSPREG_ICR_DMA_IDLE_DOMAIN
|
DSPREG_ICR_DPLL_IDLE_DOMAIN
);
icrh
=
icr_tmp
>>
8
;
icrl
=
icr_tmp
&
0xff
;
{
unsigned
char
idle_text
[
IDLE_TEXT_SIZE
]
=
IDLE_TEXT
(
icr
);
unsigned
char
idle_text
[
CPU_IDLE_TEXT_SIZE
]
=
CPU_IDLE_TEXT_INIT
(
icrh
,
icrl
);
simple_load_code
(
idle_text
,
dspbyte_to_virt
(
idle_boot_base
),
IDLE_TEXT_SIZE
);
CPU_
IDLE_TEXT_SIZE
);
}
if
(
idle_boot_base
==
DSP_BOOT_ADR_MPUI
)
omap_writew
(
MPUI_DSP_BOOT_CONFIG_MPUI
,
MPUI_DSP_BOOT_CONFIG
);
else
dsp_set_rstvect
(
idle_boot_base
);
clk_unuse
(
api_ck_handle
);
udelay
(
10
);
/* to make things stable */
__dsp_run
();
dsp_runstat
=
RUNSTAT_IDLE
;
preempt_enable
();
enable_irq
(
INT_DSP_MMU
);
udelay
(
100
);
/* to make things stable */
clk_unuse
(
api_ck_handle
);
}
void
dsp_set_idle_boot_base
(
unsigned
long
adr
,
size_t
size
)
...
...
@@ -154,13 +224,18 @@ void dsp_set_idle_boot_base(unsigned long adr, size_t size)
if
(
adr
==
idle_boot_base
)
return
;
idle_boot_base
=
adr
;
if
(
size
<
IDLE_TEXT_SIZE
)
{
if
((
size
<
GBL_IDLE_TEXT_SIZE
)
||
(
size
<
CPU_IDLE_TEXT_SIZE
))
{
printk
(
KERN_ERR
"omapdsp: size for idle program is not enough!
\n
"
);
BUG
();
}
if
(
dsp_runstat
==
RUNSTAT_IDLE
)
dsp_idle
();
/* restart idle program with new base address */
if
(
cpustat
.
stat
==
CPUSTAT_GBL_IDLE
)
dsp_gbl_idle
();
if
(
cpustat
.
stat
==
CPUSTAT_CPU_IDLE
)
dsp_cpu_idle
();
}
static
unsigned
short
save_dsp_idlect2
;
...
...
@@ -197,9 +272,10 @@ void omap_dsp_pm_resume(void)
omap_writew
(
save_arm_idlect2
,
ARM_IDLECT2
);
/* Run DSP, if it was running */
if
(
dsp_runstat
!=
RUN
STAT_RESET
)
if
(
cpustat
.
stat
!=
CPU
STAT_RESET
)
__dsp_run
();
}
static
int
init_done
;
static
int
__init
omap_dsp_init
(
void
)
...
...
@@ -209,12 +285,20 @@ static int __init omap_dsp_init(void)
if
(
cpu_is_omap1510
())
{
dspmem_base
=
OMAP1510_DSP_BASE
;
dspmem_size
=
OMAP1510_DSP_SIZE
;
daram_base
=
OMAP1510_DARAM_BASE
;
daram_size
=
OMAP1510_DARAM_SIZE
;
saram_base
=
OMAP1510_SARAM_BASE
;
saram_size
=
OMAP1510_SARAM_SIZE
;
}
#endif
#ifdef CONFIG_ARCH_OMAP16XX
if
(
cpu_is_omap16xx
())
{
dspmem_base
=
OMAP16XX_DSP_BASE
;
dspmem_size
=
OMAP16XX_DSP_SIZE
;
daram_base
=
OMAP16XX_DARAM_BASE
;
daram_size
=
OMAP16XX_DARAM_SIZE
;
saram_base
=
OMAP16XX_SARAM_BASE
;
saram_size
=
OMAP16XX_SARAM_SIZE
;
}
#endif
if
(
dspmem_size
==
0
)
{
...
...
@@ -243,31 +327,228 @@ static int __init omap_dsp_init(void)
return
0
;
}
void
omap_dsp_request_idl
e
(
void
)
static
void
dsp_cpustat_updat
e
(
void
)
{
if
(
dsp_runstat
==
RUNSTAT_RESET
)
{
if
(
!
init_done
)
omap_dsp_init
();
dsp_idle
();
if
(
!
init_done
)
omap_dsp_init
();
if
(
cpustat
.
req
==
CPUSTAT_RUN
)
{
if
(
cpustat
.
stat
<
CPUSTAT_RUN
)
{
__dsp_reset
();
clk_use
(
api_ck_handle
);
udelay
(
10
);
__dsp_run
();
cpustat
.
stat
=
CPUSTAT_RUN
;
enable_irq
(
INT_DSP_MMU
);
}
return
;
}
/* cpustat.stat < CPUSTAT_RUN */
if
(
cpustat
.
stat
==
CPUSTAT_RUN
)
{
disable_irq
(
INT_DSP_MMU
);
clk_unuse
(
api_ck_handle
);
}
/*
* (1) when ARM wants DARAM access, MPUI should be SAM and
* DSP needs to be on.
* (2) if any bits of icr is masked, we can not enter global idle.
*/
if
((
cpustat
.
req
==
CPUSTAT_CPU_IDLE
)
||
(
cpustat
.
usecount
.
mem
>
0
)
||
(
cpustat
.
usecount
.
mem_delayed
>
0
)
||
((
cpustat
.
usecount
.
mpui
>
0
)
&&
(
cpustat
.
icrmask
!=
0xffff
)))
{
if
(
cpustat
.
stat
!=
CPUSTAT_CPU_IDLE
)
{
dsp_cpu_idle
();
cpustat
.
stat
=
CPUSTAT_CPU_IDLE
;
}
return
;
}
/*
* when ARM only needs MPUI access, MPUI can be HOM and
* DSP can be idling.
*/
if
((
cpustat
.
req
==
CPUSTAT_GBL_IDLE
)
||
(
cpustat
.
usecount
.
mpui
>
0
))
{
if
(
cpustat
.
stat
!=
CPUSTAT_GBL_IDLE
)
{
dsp_gbl_idle
();
cpustat
.
stat
=
CPUSTAT_GBL_IDLE
;
}
return
;
}
/*
* no user, no request
*/
if
(
cpustat
.
stat
!=
CPUSTAT_RESET
)
{
__dsp_reset
();
cpustat
.
stat
=
CPUSTAT_RESET
;
}
}
void
dsp_cpustat_request
(
enum
e_cpustat
req
)
{
down
(
&
cpustat
.
sem
);
cpustat
.
req
=
req
;
dsp_cpustat_update
();
up
(
&
cpustat
.
sem
);
}
enum
e_cpustat
dsp_cpustat_get_stat
(
void
)
{
return
cpustat
.
stat
;
}
unsigned
short
dsp_cpustat_get_icrmask
(
void
)
{
return
cpustat
.
icrmask
;
}
void
dsp_cpustat_set_icrmask
(
unsigned
short
mask
)
{
down
(
&
cpustat
.
sem
);
cpustat
.
icrmask
=
mask
;
dsp_cpustat_update
();
up
(
&
cpustat
.
sem
);
}
void
omap_dsp_request_mpui
(
void
)
{
down
(
&
cpustat
.
sem
);
if
(
cpustat
.
usecount
.
mpui
++
==
0
)
dsp_cpustat_update
();
up
(
&
cpustat
.
sem
);
}
void
omap_dsp_release_mpui
(
void
)
{
down
(
&
cpustat
.
sem
);
if
(
cpustat
.
usecount
.
mpui
--
==
0
)
{
printk
(
KERN_ERR
"omapdsp: unbalanced mpui request/release detected.
\n
"
" cpustat.usecount.mpui is going to be "
"less than zero! ... fixed to be zero.
\n
"
);
cpustat
.
usecount
.
mpui
=
0
;
}
if
(
cpustat
.
usecount
.
mpui
==
0
)
dsp_cpustat_update
();
up
(
&
cpustat
.
sem
);
}
int
omap_dsp_request_mem
(
void
)
{
int
ret
=
0
;
down
(
&
cpustat
.
sem
);
if
((
cpustat
.
usecount
.
mem
++
==
0
)
&&
(
cpustat
.
usecount
.
mem_delayed
==
0
))
{
if
(
cpustat
.
mem_req_cb
)
{
if
((
ret
=
cpustat
.
mem_req_cb
())
<
0
)
{
cpustat
.
usecount
.
mem
--
;
goto
out
;
}
}
dsp_cpustat_update
();
}
out:
up
(
&
cpustat
.
sem
);
return
ret
;
}
/*
* release_mem will be delayed.
*/
static
void
do_release_mem
(
void
)
{
down
(
&
cpustat
.
sem
);
cpustat
.
usecount
.
mem_delayed
=
0
;
if
(
cpustat
.
usecount
.
mem
==
0
)
{
dsp_cpustat_update
();
if
(
cpustat
.
mem_rel_cb
)
cpustat
.
mem_rel_cb
();
}
up
(
&
cpustat
.
sem
);
}
static
DECLARE_WORK
(
mem_rel_work
,
(
void
(
*
)(
void
*
))
do_release_mem
,
NULL
);
int
omap_dsp_release_mem
(
void
)
{
down
(
&
cpustat
.
sem
);
/* cancel previous release work */
cancel_delayed_work
(
&
mem_rel_work
);
cpustat
.
usecount
.
mem_delayed
=
0
;
if
(
cpustat
.
usecount
.
mem
--
==
0
)
{
printk
(
KERN_ERR
"omapdsp: unbalanced memory request/release detected.
\n
"
" cpustat.usecount.mem is going to be "
"less than zero! ... fixed to be zero.
\n
"
);
cpustat
.
usecount
.
mem
=
0
;
}
if
(
cpustat
.
usecount
.
mem
==
0
)
{
cpustat
.
usecount
.
mem_delayed
=
1
;
schedule_delayed_work
(
&
mem_rel_work
,
HZ
);
}
up
(
&
cpustat
.
sem
);
return
0
;
}
void
dsp_register_mem_cb
(
int
(
*
req_cb
)(
void
),
void
(
*
rel_cb
)(
void
))
{
down
(
&
cpustat
.
sem
);
cpustat
.
mem_req_cb
=
req_cb
;
cpustat
.
mem_rel_cb
=
rel_cb
;
/*
* This function must be called while mem is enabled!
*/
BUG_ON
(
cpustat
.
usecount
.
mem
==
0
);
up
(
&
cpustat
.
sem
);
}
void
dsp_unregister_mem_cb
(
void
)
{
down
(
&
cpustat
.
sem
);
cpustat
.
mem_req_cb
=
NULL
;
cpustat
.
mem_rel_cb
=
NULL
;
up
(
&
cpustat
.
sem
);
}
arch_initcall
(
omap_dsp_init
);
EXPORT_SYMBOL
(
omap_dsp_pm_suspend
);
EXPORT_SYMBOL
(
omap_dsp_pm_resume
);
EXPORT_SYMBOL
(
omap_dsp_request_idle
);
EXPORT_SYMBOL
(
omap_dsp_request_mpui
);
EXPORT_SYMBOL
(
omap_dsp_release_mpui
);
EXPORT_SYMBOL
(
omap_dsp_request_mem
);
EXPORT_SYMBOL
(
omap_dsp_release_mem
);
#ifdef CONFIG_OMAP_DSP_MODULE
EXPORT_SYMBOL
(
dsp_ck_handle
);
EXPORT_SYMBOL
(
api_ck_handle
);
EXPORT_SYMBOL
(
dspmem_base
);
EXPORT_SYMBOL
(
dspmem_size
);
EXPORT_SYMBOL
(
dsp_runstat
);
EXPORT_SYMBOL
(
dsp_icrmask
);
EXPORT_SYMBOL
(
daram_base
);
EXPORT_SYMBOL
(
daram_size
);
EXPORT_SYMBOL
(
saram_base
);
EXPORT_SYMBOL
(
saram_size
);
EXPORT_SYMBOL
(
dsp_set_rstvect
);
EXPORT_SYMBOL
(
dsp_idle
);
EXPORT_SYMBOL
(
dsp_set_idle_boot_base
);
EXPORT_SYMBOL
(
dsp_cpustat_request
);
EXPORT_SYMBOL
(
dsp_cpustat_get_stat
);
EXPORT_SYMBOL
(
dsp_cpustat_get_icrmask
);
EXPORT_SYMBOL
(
dsp_cpustat_set_icrmask
);
EXPORT_SYMBOL
(
dsp_register_mem_cb
);
EXPORT_SYMBOL
(
dsp_unregister_mem_cb
);
EXPORT_SYMBOL
(
__cpu_flush_kern_tlb_range
);
#endif
arch/arm/plat-omap/dsp/dsp_common.h
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 200
4/11/16: DSP Gateway version 3.2
* 200
5/06/13: DSP Gateway version 3.3
*/
#include "hardware_dsp.h"
...
...
@@ -52,28 +52,28 @@
* default setting: wordswap = all, byteswap = APIMEM only
*/
#define mpui_wordswap_on() \
{ \
do
{ \
omap_writel( \
(omap_readl(MPUI_CTRL) & ~MPUI_CTRL_WORDSWAP_MASK) | \
MPUI_CTRL_WORDSWAP_ALL, MPUI_CTRL); \
} while(0)
#define mpui_wordswap_off() \
{ \
do
{ \
omap_writel( \
(omap_readl(MPUI_CTRL) & ~MPUI_CTRL_WORDSWAP_MASK) | \
MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL); \
} while(0)
#define mpui_byteswap_on() \
{ \
do
{ \
omap_writel( \
(omap_readl(MPUI_CTRL) & ~MPUI_CTRL_BYTESWAP_MASK) | \
MPUI_CTRL_BYTESWAP_API, MPUI_CTRL); \
} while(0)
#define mpui_byteswap_off() \
{ \
do
{ \
omap_writel( \
(omap_readl(MPUI_CTRL) & ~MPUI_CTRL_BYTESWAP_MASK) | \
MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL); \
...
...
@@ -83,13 +83,13 @@
* TC wordswap on / off
*/
#define tc_wordswap() \
{ \
do
{ \
omap_writel(TC_ENDIANISM_SWAP_WORD | TC_ENDIANISM_EN, \
TC_ENDIANISM); \
} while(0)
#define tc_noswap() \
{ \
do
{ \
omap_writel(omap_readl(TC_ENDIANISM) & ~TC_ENDIANISM_EN, \
TC_ENDIANISM); \
} while(0)
...
...
@@ -102,16 +102,31 @@
#define __dsp_run() omap_set_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
#define __dsp_reset() omap_clr_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
#define RUNSTAT_RESET 0
#define RUNSTAT_IDLE 1
#define RUNSTAT_RUN 2
extern
struct
clk
*
dsp_ck_handle
;
extern
struct
clk
*
api_ck_handle
;
extern
unsigned
long
dspmem_base
,
dspmem_size
;
extern
int
dsp_runstat
;
extern
unsigned
short
dsp_icrmask
;
extern
unsigned
long
dspmem_base
,
dspmem_size
,
daram_base
,
daram_size
,
saram_base
,
saram_size
;
enum
e_cpustat
{
CPUSTAT_RESET
=
0
,
CPUSTAT_GBL_IDLE
=
1
,
CPUSTAT_CPU_IDLE
=
2
,
CPUSTAT_RUN
=
3
};
#define cpustat_name(stat) \
((stat == CPUSTAT_RESET) ? "RESET" :\
(stat == CPUSTAT_GBL_IDLE) ? "GBL_IDLE" :\
(stat == CPUSTAT_CPU_IDLE) ? "CPU_IDLE" :\
(stat == CPUSTAT_RUN) ? "RUN" :\
"unknown")
int
dsp_set_rstvect
(
unsigned
long
adr
);
void
dsp_idle
(
void
);
void
dsp_set_idle_boot_base
(
unsigned
long
adr
,
size_t
size
);
void
dsp_cpustat_request
(
enum
e_cpustat
req
);
enum
e_cpustat
dsp_cpustat_get_stat
(
void
);
unsigned
short
dsp_cpustat_get_icrmask
(
void
);
void
dsp_cpustat_set_icrmask
(
unsigned
short
mask
);
void
dsp_register_mem_cb
(
int
(
*
req_cb
)(
void
),
void
(
*
rel_cb
)(
void
));
void
dsp_unregister_mem_cb
(
void
);
arch/arm/plat-omap/dsp/dsp_core.c
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2005/0
2/15: DSP Gateway version 3.2
* 2005/0
6/07: DSP Gateway version 3.3
*/
#include <linux/init.h>
...
...
@@ -55,17 +55,11 @@ enum mbseq_check_level {
};
static
enum
mbseq_check_level
mbseq_check_level
=
MBSEQ_CHECK_VERBOSE
;
static
unsigned
short
mbseq_send
;
static
unsigned
short
mbseq_expect
;
struct
sync_seq
{
unsigned
short
da_dsp
;
unsigned
short
da_arm
;
unsigned
short
ad_dsp
;
unsigned
short
ad_arm
;
};
static
struct
sync_seq
*
sync_seq
;
static
int
mbx1_valid
;
static
struct
sync_seq
*
mbseq
;
static
unsigned
short
mbseq_expect_tmp
;
static
unsigned
short
*
mbseq_expect
=
&
mbseq_expect_tmp
;
/*
* mailbox commands
...
...
@@ -78,7 +72,11 @@ extern void mbx1_bkyld(struct mbcmd *mb);
extern
void
mbx1_bksndp
(
struct
mbcmd
*
mb
);
extern
void
mbx1_bkreqp
(
struct
mbcmd
*
mb
);
extern
void
mbx1_tctl
(
struct
mbcmd
*
mb
);
extern
void
mbx1_poll
(
struct
mbcmd
*
mb
);
#ifdef OLD_BINARY_SUPPORT
/* v3.3 obsolete */
extern
void
mbx1_wdt
(
struct
mbcmd
*
mb
);
#endif
extern
void
mbx1_suspend
(
struct
mbcmd
*
mb
);
static
void
mbx1_kfunc
(
struct
mbcmd
*
mb
);
extern
void
mbx1_tcfg
(
struct
mbcmd
*
mb
);
...
...
@@ -100,7 +98,11 @@ static const struct cmdinfo
cif_bksndp
=
{
"BKSNDP"
,
CMD_L_TYPE_TID
,
mbx1_bksndp
},
cif_bkreqp
=
{
"BKREQP"
,
CMD_L_TYPE_TID
,
mbx1_bkreqp
},
cif_tctl
=
{
"TCTL"
,
CMD_L_TYPE_TID
,
mbx1_tctl
},
cif_poll
=
{
"POLL"
,
CMD_L_TYPE_NULL
,
mbx1_poll
},
#ifdef OLD_BINARY_SUPPORT
/* v3.3 obsolete */
cif_wdt
=
{
"WDT"
,
CMD_L_TYPE_NULL
,
mbx1_wdt
},
#endif
cif_runlevel
=
{
"RUNLEVEL"
,
CMD_L_TYPE_SUBCMD
,
NULL
},
cif_pm
=
{
"PM"
,
CMD_L_TYPE_SUBCMD
,
NULL
},
cif_suspend
=
{
"SUSPEND"
,
CMD_L_TYPE_NULL
,
mbx1_suspend
},
...
...
@@ -129,7 +131,7 @@ const struct cmdinfo *cmdinfo[128] = {
&
cif_bksndp
,
&
cif_bkreqp
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
/*30*/
&
cif_tctl
,
&
cif_null
,
&
cif_
nu
ll
,
&
cif_null
,
/*30*/
&
cif_tctl
,
&
cif_null
,
&
cif_
po
ll
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
...
...
@@ -137,7 +139,12 @@ const struct cmdinfo *cmdinfo[128] = {
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
#ifdef OLD_BINARY_SUPPORT
/* v3.3 obsolete */
/*50*/
&
cif_wdt
,
&
cif_runlevel
,
&
cif_pm
,
&
cif_suspend
,
#else
/*50*/
&
cif_null
,
&
cif_runlevel
,
&
cif_pm
,
&
cif_suspend
,
#endif
&
cif_kfunc
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
&
cif_null
,
...
...
@@ -207,7 +214,7 @@ static __inline__ int mbsync_irq_save(unsigned long *flags, int try_cnt)
#define print_mb_mmu_abort(mb) do {} while(0)
#endif
/* !CONFIG_OMAP_DSP_MBCMD_VERBOSE */
int
__mbsend
(
struct
mbcmd
*
mb
)
int
__mb
cmd_
send
(
struct
mbcmd
*
mb
)
{
struct
mbcmd_hw
*
mb_hw
=
(
struct
mbcmd_hw
*
)
mb
;
unsigned
long
flags
;
...
...
@@ -220,12 +227,13 @@ int __mbsend(struct mbcmd *mb)
return
-
1
;
}
mb
->
seq
=
mbseq_send
&
1
;
mbseq_send
++
;
if
(
sync_seq
)
sync_seq
->
ad_arm
=
mbseq_send
;
mblog_add
(
mb
,
MBLOG_DIR_AD
);
mblog_printcmd
(
mb
,
MBLOG_DIR_AD
);
if
(
mbseq
)
{
mb
->
seq
=
mbseq
->
ad_arm
;
mbseq
->
ad_arm
++
;
}
else
mb
->
seq
=
0
;
mblog_add
(
mb
,
DIR_A2D
);
mblog_printcmd
(
mb
,
DIR_A2D
);
omap_writew
(
mb_hw
->
data
,
MAILBOX_ARM2DSP1
);
omap_writew
(
mb_hw
->
cmd
,
MAILBOX_ARM2DSP1b
);
...
...
@@ -235,9 +243,9 @@ int __mbsend(struct mbcmd *mb)
}
/*
* __dsp_mbsend(): mailbox dispatcher
* __dsp_mb
cmd_
send(): mailbox dispatcher
*/
int
__dsp_mbsend
(
struct
mbcmd
*
mb
,
struct
mb_exarg
*
arg
,
int
recovery_flag
)
int
__dsp_mb
cmd_
send
(
struct
mbcmd
*
mb
,
struct
mb_exarg
*
arg
,
int
recovery_flag
)
{
static
DECLARE_MUTEX
(
mbsend_sem
);
int
ret
=
0
;
...
...
@@ -257,10 +265,18 @@ int __dsp_mbsend(struct mbcmd *mb, struct mb_exarg *arg, int recovery_flag)
if
(
arg
)
{
/* we have extra argument */
int
i
;
if
(
__dsp_mem_enable
(
ipbuf_sys_ad
)
<
0
)
goto
out
;
/*
* even if ipbuf_sys_ad is in DSP internal memory,
* dsp_mem_enable() never cause to call PM mailbox command
* because in that case DSP memory should be always enabled.
* (see ipbuf_sys_hold_mem_active in ipbuf.c)
*
* Therefore, we can call this function here safely.
*/
dsp_mem_enable
(
ipbuf_sys_ad
);
if
(
sync_with_dsp
(
&
ipbuf_sys_ad
->
s
,
OMAP_DSP_TID_FREE
,
10
)
<
0
)
{
printk
(
KERN_ERR
"omapdsp: ipbuf_sys_ad is busy.
\n
"
);
dsp_mem_disable
(
ipbuf_sys_ad
);
ret
=
-
EBUSY
;
goto
out
;
}
...
...
@@ -268,19 +284,18 @@ int __dsp_mbsend(struct mbcmd *mb, struct mb_exarg *arg, int recovery_flag)
ipbuf_sys_ad
->
d
[
i
]
=
arg
->
argv
[
i
];
}
ipbuf_sys_ad
->
s
=
arg
->
tid
;
if
(
__dsp_mem_disable
(
ipbuf_sys_ad
)
<
0
)
goto
out
;
dsp_mem_disable
(
ipbuf_sys_ad
);
}
ret
=
__mbsend
(
mb
);
ret
=
__mb
cmd_
send
(
mb
);
out:
up
(
&
mbsend_sem
);
return
ret
;
}
int
__dsp_mbsend_and_wait
(
struct
mbcmd
*
mb
,
struct
mb_exarg
*
arg
,
wait_queue_head_t
*
q
)
int
__dsp_mb
cmd_
send_and_wait
(
struct
mbcmd
*
mb
,
struct
mb_exarg
*
arg
,
wait_queue_head_t
*
q
)
{
long
current_state
;
DECLARE_WAITQUEUE
(
wait
,
current
);
...
...
@@ -288,36 +303,72 @@ int __dsp_mbsend_and_wait(struct mbcmd *mb, struct mb_exarg *arg,
add_wait_queue
(
q
,
&
wait
);
current_state
=
current
->
state
;
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
dsp_mbsend_exarg
(
mb
,
arg
)
<
0
)
{
if
(
dsp_mb
cmd_
send_exarg
(
mb
,
arg
)
<
0
)
{
set_current_state
(
current_state
);
remove_wait_queue
(
q
,
&
wait
);
return
-
1
;
}
schedule
(
);
schedule
_timeout
(
DSP_TIMEOUT
);
set_current_state
(
current_state
);
remove_wait_queue
(
q
,
&
wait
);
return
0
;
}
int
__dsp_mbsend
(
unsigned
char
cmdh
,
unsigned
char
cmdl
,
unsigned
short
data
,
int
recovery_flag
)
{
struct
mbcmd
mb
;
mbcmd_set
(
mb
,
cmdh
,
cmdl
,
data
);
return
__dsp_mbcmd_send
(
&
mb
,
NULL
,
recovery_flag
);
}
static
int
mbsync_hold_mem_active
;
void
dsp_mb_start
(
void
)
{
mb
seq_send
=
0
;
mbseq_expect
=
0
;
mb
x1_valid
=
1
;
/* start interpreting */
mbseq_expect
_tmp
=
0
;
}
void
dsp_mb_stop
(
void
)
{
sync_seq
=
NULL
;
mbx1_valid
=
0
;
/* stop interpreting */
if
(
mbsync_hold_mem_active
)
{
dsp_mem_disable
((
void
*
)
daram_base
);
mbsync_hold_mem_active
=
0
;
}
mbseq
=
NULL
;
mbseq_expect
=
&
mbseq_expect_tmp
;
}
/*
* dsp_mb_config() is called from mbx1 workqueue
*/
void
dsp_mb_config
(
void
*
sync_seq_adr
)
int
dsp_mb_config
(
void
*
p
)
{
sync_seq
=
sync_seq_adr
;
sync_seq
->
da_arm
=
mbseq_expect
;
unsigned
long
flags
;
if
(
dsp_address_validate
(
p
,
sizeof
(
struct
sync_seq
),
"mbseq"
)
<
0
)
return
-
1
;
if
(
dsp_mem_type
(
p
,
sizeof
(
struct
sync_seq
))
!=
MEM_TYPE_EXTERN
)
{
printk
(
KERN_WARNING
"omapdsp: mbseq is placed in DSP internal memory.
\n
"
" It will prevent DSP from idling.
\n
"
);
mbsync_hold_mem_active
=
1
;
/*
* dsp_mem_enable() never fails because
* it has been already enabled in dspcfg process and
* this will just increment the usecount.
*/
dsp_mem_enable
((
void
*
)
daram_base
);
}
local_irq_save
(
flags
);
mbseq
=
p
;
mbseq
->
da_arm
=
mbseq_expect_tmp
;
mbseq_expect
=
&
mbseq
->
da_arm
;
local_irq_restore
(
flags
);
return
0
;
}
/*
...
...
@@ -351,8 +402,8 @@ static void do_mbx1(void)
mb
=
&
mbq
.
mb
[
mbq
.
rp
];
mblog_add
(
mb
,
MBLOG_DIR_D
A
);
mblog_printcmd
(
mb
,
MBLOG_DIR_D
A
);
mblog_add
(
mb
,
DIR_D2
A
);
mblog_printcmd
(
mb
,
DIR_D2
A
);
/*
* call handler for each command
...
...
@@ -386,7 +437,6 @@ static DECLARE_WORK(mbx1_work, (void (*)(void *))do_mbx1, NULL);
/*
* kernel function dispatcher
*/
#ifdef CONFIG_FB_OMAP_EXTERNAL_LCDC
extern
void
mbx1_fbctl_disable
(
void
);
static
void
mbx1_kfunc_fbctl
(
unsigned
short
data
)
...
...
@@ -400,16 +450,13 @@ static void mbx1_kfunc_fbctl(unsigned short data)
"mailbox: Unknown FBCTL from DSP: 0x%04x
\n
"
,
data
);
}
}
#endif
static
void
mbx1_kfunc
(
struct
mbcmd
*
mb
)
{
switch
(
mb
->
cmd_l
)
{
#ifdef CONFIG_FB_OMAP_EXTERNAL_LCDC
case
OMAP_DSP_MBCMD_KFUNC_FBCTL
:
mbx1_kfunc_fbctl
(
mb
->
data
);
break
;
#endif
default:
printk
(
KERN_ERR
...
...
@@ -435,7 +482,11 @@ static irqreturn_t mbx1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
mb
->
hw
.
cmd
=
omap_readw
(
MAILBOX_DSP2ARM2b
);
#endif
if
(
mb
->
sw
.
seq
!=
(
mbseq_expect
&
1
))
{
/* if mbx1 has not been validated yet, discard. */
if
(
!
mbx1_valid
)
return
IRQ_HANDLED
;
if
(
mb
->
sw
.
seq
!=
(
*
mbseq_expect
&
1
))
{
switch
(
mbseq_check_level
)
{
case
MBSEQ_CHECK_NONE
:
break
;
...
...
@@ -449,9 +500,7 @@ static irqreturn_t mbx1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
}
mbseq_expect
++
;
if
(
sync_seq
)
sync_seq
->
da_arm
=
mbseq_expect
;
(
*
mbseq_expect
)
++
;
mbq_inc
(
mbq
.
wp
);
if
(
mbq
.
wp
==
mbq
.
rp
)
{
/* mbq is full */
...
...
@@ -585,6 +634,9 @@ static int __init dsp_drv_probe(struct device *dev)
goto
fail6
;
}
/* MMU interrupt is not enabled until DSP runs */
disable_irq
(
INT_DSP_MMU
);
#if 0
ret = request_irq(INT_MPUIO, mpuio_interrupt, SA_INTERRUPT, "dsp", dev);
if (ret) {
...
...
@@ -617,7 +669,7 @@ fail1:
static
int
dsp_drv_remove
(
struct
device
*
dev
)
{
__dsp_reset
(
);
dsp_cpustat_request
(
CPUSTAT_RESET
);
#if 0
free_irq(INT_MPUIO, dev);
...
...
@@ -626,6 +678,9 @@ static int dsp_drv_remove(struct device *dev)
free_irq
(
INT_D2A_MB2
,
dev
);
free_irq
(
INT_D2A_MB1
,
dev
);
/* recover disable_depth */
enable_irq
(
INT_DSP_MMU
);
dspuncfg
();
dsp_taskmod_exit
();
mblog_exit
();
...
...
arch/arm/plat-omap/dsp/dsp_ctl.c
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2005/0
2/17: DSP Gateway version 3.2
* 2005/0
6/09: DSP Gateway version 3.3
*/
#include <linux/module.h>
...
...
@@ -47,12 +47,12 @@ static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
static
struct
device_attribute
dev_attr_loadinfo
=
__ATTR_RO
(
loadinfo
);
extern
struct
device_attribute
dev_attr_ipbuf
;
static
enum
{
static
enum
cfgstat
{
CFG_ERR
,
CFG_READY
,
CFG_SUSPEND
}
cfgstat
;
static
int
mbx_revision
;
int
mbx_revision
;
static
DECLARE_WAIT_QUEUE_HEAD
(
ioctl_wait_q
);
static
unsigned
short
ioctl_wait_cmd
;
static
DECLARE_MUTEX
(
ioctl_sem
);
...
...
@@ -62,33 +62,6 @@ static unsigned char n_stask;
/*
* control functions
*/
static
void
dsp_run
(
void
)
{
disable_irq
(
INT_DSP_MMU
);
preempt_disable
();
if
(
dsp_runstat
==
RUNSTAT_RESET
)
{
clk_use
(
api_ck_handle
);
__dsp_run
();
dsp_runstat
=
RUNSTAT_RUN
;
}
preempt_enable
();
enable_irq
(
INT_DSP_MMU
);
}
static
void
dsp_reset
(
void
)
{
disable_irq
(
INT_DSP_MMU
);
preempt_disable
();
if
(
dsp_runstat
>
RUNSTAT_RESET
)
{
__dsp_reset
();
if
(
dsp_runstat
==
RUNSTAT_RUN
)
clk_unuse
(
api_ck_handle
);
dsp_runstat
=
RUNSTAT_RESET
;
}
preempt_enable
();
enable_irq
(
INT_DSP_MMU
);
}
static
short
varread_val
[
5
];
/* maximum */
static
int
dsp_regread
(
unsigned
short
cmd_l
,
unsigned
short
adr
,
...
...
@@ -102,7 +75,7 @@ static int dsp_regread(unsigned short cmd_l, unsigned short adr,
ioctl_wait_cmd
=
MBCMD
(
REGRW
);
mbcmd_set
(
mb
,
MBCMD
(
REGRW
),
cmd_l
,
adr
);
dsp_mbsend_and_wait
(
&
mb
,
&
ioctl_wait_q
);
dsp_mb
cmd_
send_and_wait
(
&
mb
,
&
ioctl_wait_q
);
if
(
ioctl_wait_cmd
!=
0
)
{
printk
(
KERN_ERR
"omapdsp: register read error!
\n
"
);
...
...
@@ -128,7 +101,7 @@ static int dsp_regwrite(unsigned short cmd_l, unsigned short adr,
};
mbcmd_set
(
mb
,
MBCMD
(
REGRW
),
cmd_l
,
adr
);
dsp_mbsend_exarg
(
&
mb
,
&
arg
);
dsp_mb
cmd_
send_exarg
(
&
mb
,
&
arg
);
return
0
;
}
...
...
@@ -142,7 +115,7 @@ static int dsp_getvar(unsigned char varid, unsigned short *val, int sz)
ioctl_wait_cmd
=
MBCMD
(
GETVAR
);
mbcmd_set
(
mb
,
MBCMD
(
GETVAR
),
varid
,
0
);
dsp_mbsend_and_wait
(
&
mb
,
&
ioctl_wait_q
);
dsp_mb
cmd_
send_and_wait
(
&
mb
,
&
ioctl_wait_q
);
if
(
ioctl_wait_cmd
!=
0
)
{
printk
(
KERN_ERR
"omapdsp: variable read error!
\n
"
);
...
...
@@ -159,10 +132,7 @@ up_out:
static
int
dsp_setvar
(
unsigned
char
varid
,
unsigned
short
val
)
{
struct
mbcmd
mb
;
mbcmd_set
(
mb
,
MBCMD
(
SETVAR
),
varid
,
val
);
dsp_mbsend
(
&
mb
);
dsp_mbsend
(
MBCMD
(
SETVAR
),
varid
,
val
);
return
0
;
}
...
...
@@ -182,6 +152,15 @@ static int dspcfg(void)
goto
up_out
;
}
/* for safety */
dsp_mem_usecount_clear
();
/*
* DSPCFG command and dsp_mem_start() must be called
* while internal mem is on.
*/
dsp_mem_enable
((
void
*
)
dspmem_base
);
dsp_mb_start
();
dsp_twch_start
();
dsp_mem_start
();
...
...
@@ -190,7 +169,7 @@ static int dspcfg(void)
mbx_revision
=
-
1
;
ioctl_wait_cmd
=
MBCMD
(
DSPCFG
);
mbcmd_set
(
mb
,
MBCMD
(
DSPCFG
),
OMAP_DSP_MBCMD_DSPCFG_REQ
,
0
);
dsp_mbsend_and_wait
(
&
mb
,
&
ioctl_wait_q
);
dsp_mb
cmd_
send_and_wait
(
&
mb
,
&
ioctl_wait_q
);
if
(
ioctl_wait_cmd
!=
0
)
{
printk
(
KERN_ERR
"omapdsp: configuration error!
\n
"
);
...
...
@@ -199,16 +178,30 @@ static int dspcfg(void)
goto
up_out
;
}
#ifdef OLD_BINARY_SUPPORT
/*
* MBREV 3.2 or earlier doesn't assume DMA domain is on
* when DSPCFG command is sent
*/
if
((
mbx_revision
==
MBREV_3_0
)
||
(
mbx_revision
==
MBREV_3_2
))
{
ret
=
dsp_mbsend
(
MBCMD
(
PM
),
OMAP_DSP_MBCMD_PM_ENABLE
,
DSPREG_ICR_DMA_IDLE_DOMAIN
);
}
#endif
if
((
ret
=
dsp_task_config_all
(
n_stask
))
<
0
)
{
up
(
&
ioctl_sem
);
dspuncfg
();
dsp_mem_disable
((
void
*
)
dspmem_base
);
return
-
EINVAL
;
}
cfgstat
=
CFG_READY
;
/* send parameter */
if
((
ret
=
dsp_setvar
(
OMAP_DSP_MBCMD_VARID_ICRMASK
,
dsp_icrmask
))
<
0
)
if
((
ret
=
dsp_setvar
(
OMAP_DSP_MBCMD_VARID_ICRMASK
,
dsp_cpustat_get_icrmask
()))
<
0
)
goto
up_out
;
/* create runtime sysfs entries */
...
...
@@ -216,6 +209,7 @@ static int dspcfg(void)
device_create_file
(
&
dsp_device
.
dev
,
&
dev_attr_ipbuf
);
up_out:
dsp_mem_disable
((
void
*
)
dspmem_base
);
up
(
&
ioctl_sem
);
return
ret
;
}
...
...
@@ -229,7 +223,7 @@ int dspuncfg(void)
if
(
down_interruptible
(
&
ioctl_sem
))
return
-
ERESTARTSYS
;
/* FIXME: lock task module */
/* remove runtime sysfs entries */
...
...
@@ -238,7 +232,9 @@ int dspuncfg(void)
dsp_mb_stop
();
dsp_twch_stop
();
dsp_mem_stop
();
dsp_err_stop
();
dsp_dbg_stop
();
dsp_task_unconfig_all
();
ipbuf_stop
();
cfgstat
=
CFG_ERR
;
...
...
@@ -252,33 +248,76 @@ int dsp_is_ready(void)
return
(
cfgstat
==
CFG_READY
)
?
1
:
0
;
}
void
dsp_runlevel
(
unsigned
char
level
)
/*
* polls all tasks
*/
int
dsp_poll
(
void
)
{
struct
mbcmd
mb
;
int
ret
=
0
;
mbcmd_set
(
mb
,
MBCMD
(
RUNLEVEL
),
level
,
0
);
if
(
down_interruptible
(
&
ioctl_sem
))
return
-
ERESTARTSYS
;
ioctl_wait_cmd
=
MBCMD
(
POLL
);
mbcmd_set
(
mb
,
MBCMD
(
POLL
),
0
,
0
);
dsp_mbcmd_send_and_wait
(
&
mb
,
&
ioctl_wait_q
);
if
(
ioctl_wait_cmd
!=
0
)
{
printk
(
KERN_ERR
"omapdsp: poll error!
\n
"
);
ret
=
-
EINVAL
;
goto
up_out
;
}
up_out:
up
(
&
ioctl_sem
);
return
ret
;
}
void
dsp_runlevel
(
unsigned
char
level
)
{
if
(
level
==
OMAP_DSP_MBCMD_RUNLEVEL_RECOVERY
)
dsp_mbsend_recovery
(
&
mb
);
dsp_mbsend_recovery
(
MBCMD
(
RUNLEVEL
),
level
,
0
);
else
dsp_mbsend
(
&
mb
);
dsp_mbsend
(
MBCMD
(
RUNLEVEL
),
level
,
0
);
}
static
enum
cfgstat
cfgstat_save_suspend
;
/*
* suspend / resume callbacks
* DSP is not reset within this code, but done in omap_pm_suspend.
* so if these functions are called as OMAP_DSP_IOCTL_SUSPEND,
* DSP should be reset / unreset out of these functions.
*/
int
dsp_suspend
(
void
)
{
struct
mbcmd
mb
;
int
ret
=
0
;
if
(
cfgstat
==
CFG_SUSPEND
)
{
printk
(
KERN_ERR
"omapdsp: DSP is already in suspend state.
\n
"
);
return
-
EINVAL
;
}
if
(
down_interruptible
(
&
ioctl_sem
))
return
-
ERESTARTSYS
;
cfgstat_save_suspend
=
cfgstat
;
if
(
!
dsp_is_ready
())
{
ret
=
-
EINVAL
;
goto
up_out
;
if
(
dsp_cpustat_get_stat
()
==
CPUSTAT_RUN
)
{
printk
(
KERN_WARNING
"omapdsp: illegal operation: trying suspend DSP "
"while it is running but has not configured "
"yet.
\n
"
" Resetting DSP...
\n
"
);
}
goto
transition
;
}
ioctl_wait_cmd
=
MBCMD
(
SUSPEND
);
mbcmd_set
(
mb
,
MBCMD
(
SUSPEND
),
0
,
0
);
dsp_mbsend_and_wait
(
&
mb
,
&
ioctl_wait_q
);
dsp_mb
cmd_
send_and_wait
(
&
mb
,
&
ioctl_wait_q
);
if
(
ioctl_wait_cmd
!=
0
)
{
printk
(
KERN_ERR
"omapdsp: DSP suspend error!
\n
"
);
...
...
@@ -287,6 +326,7 @@ int dsp_suspend(void)
}
udelay
(
100
);
transition:
cfgstat
=
CFG_SUSPEND
;
up_out:
up
(
&
ioctl_sem
);
...
...
@@ -295,29 +335,24 @@ up_out:
int
dsp_resume
(
void
)
{
if
(
cfgstat
!=
CFG_SUSPEND
)
return
0
;
if
(
cfgstat
!=
CFG_SUSPEND
)
{
printk
(
KERN_ERR
"omapdsp: DSP is not in suspend state.
\n
"
);
return
-
EINVAL
;
}
cfgstat
=
CFG_READY
;
cfgstat
=
cfgstat_save_suspend
;
return
0
;
}
static
void
dsp_fbctl_enable
(
void
)
{
#ifdef CONFIG_FB_OMAP_EXTERNAL_LCDC
struct
mbcmd
mb
;
mbcmd_set
(
mb
,
MBCMD
(
KFUNC
),
OMAP_DSP_MBCMD_KFUNC_FBCTL
,
OMAP_DSP_MBCMD_FBCTL_ENABLE
);
dsp_mbsend
(
&
mb
);
#endif
dsp_mbsend
(
MBCMD
(
KFUNC
),
OMAP_DSP_MBCMD_KFUNC_FBCTL
,
OMAP_DSP_MBCMD_FBCTL_ENABLE
);
}
static
int
dsp_fbctl_disable
(
void
)
{
int
ret
=
0
;
#ifdef CONFIG_FB_OMAP_EXTERNAL_LCDC
struct
mbcmd
mb
;
if
(
down_interruptible
(
&
ioctl_sem
))
...
...
@@ -326,13 +361,12 @@ static int dsp_fbctl_disable(void)
ioctl_wait_cmd
=
MBCMD
(
KFUNC
);
mbcmd_set
(
mb
,
MBCMD
(
KFUNC
),
OMAP_DSP_MBCMD_KFUNC_FBCTL
,
OMAP_DSP_MBCMD_FBCTL_DISABLE
);
dsp_mbsend_and_wait
(
&
mb
,
&
ioctl_wait_q
);
dsp_mb
cmd_
send_and_wait
(
&
mb
,
&
ioctl_wait_q
);
if
(
ioctl_wait_cmd
!=
0
)
{
printk
(
KERN_ERR
"omapdsp: fb disable error!
\n
"
);
ret
=
-
EINVAL
;
}
up
(
&
ioctl_sem
);
#endif
return
ret
;
}
...
...
@@ -350,19 +384,23 @@ static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
* command level 1: commands which don't need lock
*/
case
OMAP_DSP_IOCTL_RUN
:
dsp_
run
(
);
dsp_
cpustat_request
(
CPUSTAT_RUN
);
break
;
case
OMAP_DSP_IOCTL_RESET
:
dsp_
reset
(
);
dsp_
cpustat_request
(
CPUSTAT_RESET
);
break
;
case
OMAP_DSP_IOCTL_SETRSTVECT
:
ret
=
dsp_set_rstvect
((
unsigned
long
)
arg
);
break
;
case
OMAP_DSP_IOCTL_IDLE
:
dsp_idle
();
case
OMAP_DSP_IOCTL_CPU_IDLE
:
dsp_cpustat_request
(
CPUSTAT_CPU_IDLE
);
break
;
case
OMAP_DSP_IOCTL_GBL_IDLE
:
dsp_cpustat_request
(
CPUSTAT_GBL_IDLE
);
break
;
case
OMAP_DSP_IOCTL_MPUI_WORDSWAP_ON
:
...
...
@@ -389,7 +427,7 @@ static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
return
-
EFAULT
;
mb
.
cmd
=
u_cmd
.
cmd
;
mb
.
data
=
u_cmd
.
data
;
ret
=
dsp_mbsend
((
struct
mbcmd
*
)
&
mb
);
ret
=
dsp_mb
cmd_
send
((
struct
mbcmd
*
)
&
mb
);
break
;
}
...
...
@@ -425,20 +463,27 @@ static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
ret
=
dsp_task_count
();
break
;
case
OMAP_DSP_IOCTL_POLL
:
ret
=
dsp_poll
();
break
;
case
OMAP_DSP_IOCTL_FBDIS
:
ret
=
dsp_fbctl_disable
();
break
;
/*
* FIXME: cpu status control for suspend - resume
*/
case
OMAP_DSP_IOCTL_SUSPEND
:
if
((
ret
=
dsp_suspend
())
<
0
)
break
;
dsp_
reset
(
);
dsp_
cpustat_request
(
CPUSTAT_RESET
);
break
;
case
OMAP_DSP_IOCTL_RESUME
:
if
((
ret
=
dsp_resume
())
<
0
)
break
;
dsp_
run
(
);
dsp_
cpustat_request
(
CPUSTAT_RUN
);
break
;
case
OMAP_DSP_IOCTL_REGMEMR
:
...
...
@@ -547,7 +592,7 @@ void mbx1_dspcfg(struct mbcmd *mb)
{
unsigned
char
last
=
mb
->
cmd_l
&
0x80
;
unsigned
char
cfgcmd
=
mb
->
cmd_l
&
0x7f
;
static
unsigned
long
tmp_ipb
uf_sys_da
;
static
unsigned
long
tmp_ipb
_adr
;
/* mailbox protocol check */
if
(
cfgcmd
==
OMAP_DSP_MBCMD_DSPCFG_PROTREV
)
{
...
...
@@ -563,7 +608,8 @@ void mbx1_dspcfg(struct mbcmd *mb)
if
(
mbx_revision
==
OMAP_DSP_MBPROT_REVISION
)
return
;
#ifdef OLD_BINARY_SUPPORT
else
if
(
mbx_revision
==
MBREV_3_0
)
{
else
if
((
mbx_revision
==
MBREV_3_0
)
||
(
mbx_revision
==
MBREV_3_2
))
{
printk
(
KERN_WARNING
"mbx: ***** old DSP binary *****
\n
"
" Please update your DSP application.
\n
"
);
...
...
@@ -576,7 +622,7 @@ void mbx1_dspcfg(struct mbcmd *mb)
" expected=0x%04x, received=0x%04x
\n
"
,
OMAP_DSP_MBPROT_REVISION
,
mb
->
data
);
mbx_revision
=
-
1
;
goto
abort
;
goto
abort
1
;
}
}
...
...
@@ -601,15 +647,15 @@ void mbx1_dspcfg(struct mbcmd *mb)
switch
(
cfgcmd
)
{
case
OMAP_DSP_MBCMD_DSPCFG_SYSADRH
:
tmp_ipb
uf_sys_da
=
(
unsigned
long
)
mb
->
data
<<
16
;
tmp_ipb
_adr
=
(
unsigned
long
)
mb
->
data
<<
16
;
break
;
case
OMAP_DSP_MBCMD_DSPCFG_SYSADRL
:
tmp_ipb
uf_sys_da
|=
mb
->
data
;
tmp_ipb
_adr
|=
mb
->
data
;
break
;
case
OMAP_DSP_MBCMD_DSPCFG_ABORT
:
goto
abort
;
goto
abort
1
;
default:
printk
(
KERN_ERR
...
...
@@ -619,24 +665,23 @@ void mbx1_dspcfg(struct mbcmd *mb)
}
if
(
last
)
{
unsigned
long
badr
;
void
*
badr
;
unsigned
short
bln
;
unsigned
short
bsz
;
volatile
unsigned
short
*
buf
;
void
*
sync_seq
;
void
*
ipb_sys_da
,
*
ipb_sys_ad
;
void
*
mbseq
;
short
*
dbg_buf
;
unsigned
short
dbg_buf_sz
,
dbg_line_sz
;
struct
mem_sync_struct
mem_sync
,
*
mem_syncp
;
/* system IPBUF initialization */
if
(
tmp_ipbuf_sys_da
&
0x1
)
{
printk
(
KERN_ERR
"mbx: system ipbuf address (0x%lx) "
"is odd number!
\n
"
,
tmp_ipbuf_sys_da
);
goto
abort
;
}
ipbuf_sys_da
=
dspword_to_virt
(
tmp_ipbuf_sys_da
);
ipb_sys_da
=
dspword_to_virt
(
tmp_ipb_adr
);
if
(
ipbuf_sys_config
(
ipb_sys_da
,
DIR_D2A
)
<
0
)
goto
abort1
;
if
(
sync_with_dsp
(
&
ipbuf_sys_da
->
s
,
OMAP_DSP_TID_ANON
,
10
)
<
0
)
{
printk
(
KERN_ERR
"mbx: DSPCFG - IPBUF sync failed!
\n
"
);
return
;
goto
abort1
;
}
/*
* read configuration data on system IPBUF
...
...
@@ -646,47 +691,95 @@ void mbx1_dspcfg(struct mbcmd *mb)
if
(
mbx_revision
==
OMAP_DSP_MBPROT_REVISION
)
{
#endif
buf
=
ipbuf_sys_da
->
d
;
n_stask
=
buf
[
0
];
bln
=
buf
[
1
];
bsz
=
buf
[
2
];
badr
=
MKLONG
(
buf
[
3
],
buf
[
4
]);
/*ipbuf_sys_da = dspword_to_virt(MKLONG(buf[5], buf[6])); */
ipbuf_sys_ad
=
dspword_to_virt
(
MKLONG
(
buf
[
7
],
buf
[
8
]));
sync_seq
=
dspword_to_virt
(
MKLONG
(
buf
[
9
],
buf
[
10
]));
n_stask
=
buf
[
0
];
bln
=
buf
[
1
];
bsz
=
buf
[
2
];
badr
=
MKVIRT
(
buf
[
3
],
buf
[
4
]);
/* ipb_sys_da = MKVIRT(buf[5], buf[6]); */
ipb_sys_ad
=
MKVIRT
(
buf
[
7
],
buf
[
8
]);
mbseq
=
MKVIRT
(
buf
[
9
],
buf
[
10
]);
dbg_buf
=
MKVIRT
(
buf
[
11
],
buf
[
12
]);
dbg_buf_sz
=
buf
[
13
];
dbg_line_sz
=
buf
[
14
];
mem_sync
.
DARAM
=
MKVIRT
(
buf
[
15
],
buf
[
16
]);
mem_sync
.
SARAM
=
MKVIRT
(
buf
[
17
],
buf
[
18
]);
mem_sync
.
SDRAM
=
MKVIRT
(
buf
[
19
],
buf
[
20
]);
mem_syncp
=
&
mem_sync
;
#ifdef OLD_BINARY_SUPPORT
}
else
if
(
mbx_revision
==
MBREV_3_2
)
{
buf
=
ipbuf_sys_da
->
d
;
n_stask
=
buf
[
0
];
bln
=
buf
[
1
];
bsz
=
buf
[
2
];
badr
=
MKVIRT
(
buf
[
3
],
buf
[
4
]);
/* ipb_sys_da = MKVIRT(buf[5], buf[6]); */
ipb_sys_ad
=
MKVIRT
(
buf
[
7
],
buf
[
8
]);
mbseq
=
MKVIRT
(
buf
[
9
],
buf
[
10
]);
dbg_buf
=
NULL
;
dbg_buf_sz
=
0
;
dbg_line_sz
=
0
;
mem_syncp
=
NULL
;
}
else
if
(
mbx_revision
==
MBREV_3_0
)
{
buf
=
ipbuf_sys_da
->
d
;
n_stask
=
buf
[
0
];
bln
=
buf
[
1
];
bsz
=
buf
[
2
];
badr
=
MKLONG
(
buf
[
3
],
buf
[
4
]);
/* bkeep = buf[5]; */
/*ipbuf_sys_da = dspword_to_virt(MKLONG(buf[6], buf[67)); */
ipbuf_sys_ad
=
dspword_to_virt
(
MKLONG
(
buf
[
8
],
buf
[
9
]));
sync_seq
=
dspword_to_virt
(
MKLONG
(
buf
[
10
],
buf
[
11
]));
n_stask
=
buf
[
0
];
bln
=
buf
[
1
];
bsz
=
buf
[
2
];
badr
=
MKVIRT
(
buf
[
3
],
buf
[
4
]);
/* bkeep = buf[5]; */
/* ipb_sys_da = MKVIRT(buf[6], buf[7]); */
ipb_sys_ad
=
MKVIRT
(
buf
[
8
],
buf
[
9
]);
mbseq
=
MKVIRT
(
buf
[
10
],
buf
[
11
]);
dbg_buf
=
NULL
;
dbg_buf_sz
=
0
;
dbg_line_sz
=
0
;
mem_syncp
=
NULL
;
}
else
/* should not occur */
goto
abort
;
#endif
/* ipbuf_config() should be done in interrupt routine. */
if
(
ipbuf_config
(
bln
,
bsz
,
badr
)
<
0
)
goto
abort
;
goto
abort1
;
#endif
/* OLD_BINARY_SUPPORT */
ipbuf_sys_da
->
s
=
OMAP_DSP_TID_FREE
;
release_ipbuf_pvt
(
ipbuf_sys_da
)
;
/* mb_config() should be done in interrupt routine. */
dsp_mb_config
(
sync_seq
);
/*
* following configurations need to be done before
* waking up the dspcfg initiator process.
*/
if
(
ipbuf_sys_config
(
ipb_sys_ad
,
DIR_A2D
)
<
0
)
goto
abort1
;
if
(
ipbuf_config
(
bln
,
bsz
,
badr
)
<
0
)
goto
abort1
;
if
(
dsp_mb_config
(
mbseq
)
<
0
)
goto
abort2
;
if
(
dsp_dbg_config
(
dbg_buf
,
dbg_buf_sz
,
dbg_line_sz
)
<
0
)
goto
abort2
;
if
(
dsp_mem_sync_config
(
mem_syncp
)
<
0
)
goto
abort2
;
ioctl_wait_cmd
=
0
;
wake_up_interruptible
(
&
ioctl_wait_q
);
}
return
;
abort:
abort2:
ipbuf_stop
();
abort1:
wake_up_interruptible
(
&
ioctl_wait_q
);
return
;
}
void
mbx1_poll
(
struct
mbcmd
*
mb
)
{
if
(
!
waitqueue_active
(
&
ioctl_wait_q
)
||
(
ioctl_wait_cmd
!=
MBCMD
(
POLL
)))
{
printk
(
KERN_WARNING
"mbx: POLL command received, "
"but nobody is waiting for it...
\n
"
);
return
;
}
ioctl_wait_cmd
=
0
;
wake_up_interruptible
(
&
ioctl_wait_q
);
}
void
mbx1_regrw
(
struct
mbcmd
*
mb
)
{
if
(
!
waitqueue_active
(
&
ioctl_wait_q
)
||
...
...
@@ -743,7 +836,7 @@ void mbx1_getvar(struct mbcmd *mb)
for
(
i
=
0
;
i
<
5
;
i
++
)
{
varread_val
[
i
]
=
buf
[
i
];
}
ipbuf_sys_da
->
s
=
OMAP_DSP_TID_FREE
;
release_ipbuf_pvt
(
ipbuf_sys_da
)
;
break
;
}
}
...
...
@@ -765,51 +858,54 @@ static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
*
* 3.2: sysfs / udev support
* KMEM_RESERVE / KMEM_RELEASE ioctls for mem device
* 3.3: added following ioctls
* OMAP_DSP_IOCTL_GBL_IDLE
* OMAP_DSP_IOCTL_CPU_IDLE (instead of OMAP_DSP_IOCTL_IDLE)
* OMAP_DSP_IOCTL_POLL
*/
/*
* print all supporting I/F VERSIONs, like followings.
*
* len += sprintf(buf, "3.1\n");
* len += sprintf(buf, "3.2\n");
* len += sprintf(buf, "3.3\n");
*/
len
+=
sprintf
(
buf
+
len
,
"3.2
\n
"
);
len
+=
sprintf
(
buf
+
len
,
"3.3
\n
"
);
return
len
;
}
static
struct
device_attribute
dev_attr_ifver
=
__ATTR_RO
(
ifver
);
static
ssize_t
icrmask
_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
static
ssize_t
cpustat
_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
#if 0
if (dsp_is_ready()) {
int ret;
unsigned short val;
return
sprintf
(
buf
,
"%s
\n
"
,
cpustat_name
(
dsp_cpustat_get_stat
()));
}
if ((ret = dsp_getvar(OMAP_DSP_MBCMD_VARID_ICRMASK, &val, 1)) < 0)
return ret;
if (val != dsp_icrmask)
printk(KERN_WARNING
"omapdsp: icrmask value is inconsistent!\n");
}
#endif
return
sprintf
(
buf
,
"0x%04x
\n
"
,
dsp_icrmask
);
static
struct
device_attribute
dev_attr_cpustat
=
__ATTR_RO
(
cpustat
);
static
ssize_t
icrmask_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
return
sprintf
(
buf
,
"0x%04x
\n
"
,
dsp_cpustat_get_icrmask
());
}
static
ssize_t
icrmask_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
unsigned
short
mask
;
int
ret
;
if
(
!
capable
(
CAP_SYS_ADMIN
))
return
-
EPERM
;
dsp_icrmask
=
simple_strtol
(
buf
,
NULL
,
16
);
mask
=
simple_strtol
(
buf
,
NULL
,
16
);
dsp_cpustat_set_icrmask
(
mask
);
if
(
dsp_is_ready
())
{
ret
=
dsp_setvar
(
OMAP_DSP_MBCMD_VARID_ICRMASK
,
dsp_icr
mask
);
ret
=
dsp_setvar
(
OMAP_DSP_MBCMD_VARID_ICRMASK
,
mask
);
if
(
ret
<
0
)
return
ret
;
}
...
...
@@ -848,7 +944,6 @@ static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
* static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
*/
#ifdef CONFIG_FB_OMAP_EXTERNAL_LCDC
void
mbx1_fbctl_disable
(
void
)
{
if
(
!
waitqueue_active
(
&
ioctl_wait_q
)
||
...
...
@@ -861,7 +956,6 @@ void mbx1_fbctl_disable(void)
ioctl_wait_cmd
=
0
;
wake_up_interruptible
(
&
ioctl_wait_q
);
}
#endif
#ifdef CONFIG_PROC_FS
/* for backward compatibility */
...
...
@@ -902,6 +996,7 @@ struct file_operations dsp_ctl_fops = {
void
__init
dsp_ctl_init
(
void
)
{
device_create_file
(
&
dsp_device
.
dev
,
&
dev_attr_ifver
);
device_create_file
(
&
dsp_device
.
dev
,
&
dev_attr_cpustat
);
device_create_file
(
&
dsp_device
.
dev
,
&
dev_attr_icrmask
);
#ifdef CONFIG_PROC_FS
dsp_ctl_create_proc
();
...
...
@@ -911,6 +1006,7 @@ void __init dsp_ctl_init(void)
void
dsp_ctl_exit
(
void
)
{
device_remove_file
(
&
dsp_device
.
dev
,
&
dev_attr_ifver
);
device_remove_file
(
&
dsp_device
.
dev
,
&
dev_attr_cpustat
);
device_remove_file
(
&
dsp_device
.
dev
,
&
dev_attr_icrmask
);
#ifdef CONFIG_PROC_FS
dsp_ctl_remove_proc
();
...
...
arch/arm/plat-omap/dsp/dsp_ctl_core.c
View file @
b3ddf280
...
...
@@ -21,14 +21,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2005/0
2/10: DSP Gateway version 3.2
* 2005/0
7/26: DSP Gateway version 3.3
*/
#include <linux/module.h>
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/init.h>
#include <asm/arch/dsp.h>
#include "hardware_dsp.h"
...
...
@@ -75,13 +74,12 @@ static struct file_operations dsp_ctl_core_fops = {
static
const
struct
dev_list
{
unsigned
int
minor
;
char
*
devname
;
char
*
devfs_name
;
umode_t
mode
;
}
dev_list
[]
=
{
{
CTL_MINOR
,
"dspctl"
,
"dspctl/ctl"
,
S_IRUSR
|
S_IWUSR
},
{
MEM_MINOR
,
"dspmem"
,
"dspctl/mem"
,
S_IRUSR
|
S_IWUSR
|
S_IRGRP
},
{
TWCH_MINOR
,
"dsptwch"
,
"dspctl/twch"
,
S_IRUSR
|
S_IWUSR
|
S_IRGRP
},
{
ERR_MINOR
,
"dsperr"
,
"dspctl/err"
,
S_IRUSR
|
S_IRGRP
},
{
CTL_MINOR
,
"dspctl"
,
S_IRUSR
|
S_IWUSR
},
{
MEM_MINOR
,
"dspmem"
,
S_IRUSR
|
S_IWUSR
|
S_IRGRP
},
{
TWCH_MINOR
,
"dsptwch"
,
S_IRUSR
|
S_IWUSR
|
S_IRGRP
},
{
ERR_MINOR
,
"dsperr"
,
S_IRUSR
|
S_IRGRP
},
};
int
__init
dsp_ctl_core_init
(
void
)
...
...
@@ -99,15 +97,11 @@ int __init dsp_ctl_core_init(void)
}
dsp_ctl_class
=
class_create
(
THIS_MODULE
,
"dspctl"
);
devfs_mk_dir
(
"dspctl"
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dev_list
);
i
++
)
{
class_device_create
(
dsp_ctl_class
,
MKDEV
(
OMAP_DSP_CTL_MAJOR
,
dev_list
[
i
].
minor
),
NULL
,
dev_list
[
i
].
devname
);
devfs_mk_cdev
(
MKDEV
(
OMAP_DSP_CTL_MAJOR
,
dev_list
[
i
].
minor
),
S_IFCHR
|
dev_list
[
i
].
mode
,
dev_list
[
i
].
devfs_name
);
}
return
0
;
...
...
@@ -118,12 +112,10 @@ void dsp_ctl_core_exit(void)
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dev_list
);
i
++
)
{
devfs_remove
(
dev_list
[
i
].
devfs_name
);
class_device_destroy
(
dsp_ctl_class
,
MKDEV
(
OMAP_DSP_CTL_MAJOR
,
dev_list
[
i
].
minor
));
}
devfs_remove
(
"dspctl"
);
class_destroy
(
dsp_ctl_class
);
unregister_chrdev
(
OMAP_DSP_CTL_MAJOR
,
"dspctl"
);
...
...
arch/arm/plat-omap/dsp/dsp_mem.c
View file @
b3ddf280
...
...
@@ -22,7 +22,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
* 2005/0
2/17: DSP Gateway version 3.2
* 2005/0
6/09: DSP Gateway version 3.3
*/
#include <linux/module.h>
...
...
@@ -42,8 +42,8 @@
#include <asm/hardware/clock.h>
#include <asm/arch/tc.h>
#include <asm/arch/dsp.h>
#include <asm/arch/dsp_common.h>
#include "uaccess_dsp.h"
#include "ipbuf.h"
#include "dsp.h"
#define SZ_1MB 0x100000
...
...
@@ -99,9 +99,12 @@ enum exmap_type {
struct
exmap_tbl
{
unsigned
int
valid
:
1
;
unsigned
int
cntnu
:
1
;
/* grouping */
int
usecount
;
/* reference count by mmap */
enum
exmap_type
type
;
void
*
buf
;
void
*
vadr
;
void
*
buf
;
/* virtual address of the buffer,
* i.e. 0xc0000000 - */
void
*
vadr
;
/* DSP shadow space,
* i.e. 0xe0000000 - 0xe0ffffff */
unsigned
int
order
;
};
#define DSPMMU_TLB_LINES 32
...
...
@@ -112,6 +115,7 @@ static int dsp_exunmap(unsigned long dspadr);
static
void
*
dspvect_page
;
static
unsigned
long
dsp_fault_adr
;
static
struct
mem_sync_struct
mem_sync
;
static
__inline__
unsigned
long
lineup_offset
(
unsigned
long
adr
,
unsigned
long
ref
,
...
...
@@ -125,6 +129,47 @@ static __inline__ unsigned long lineup_offset(unsigned long adr,
return
newadr
;
}
void
dsp_mem_sync_inc
(
void
)
{
/*
* FIXME: dsp_mem_enable()!!!
*/
if
(
mem_sync
.
DARAM
)
mem_sync
.
DARAM
->
ad_arm
++
;
if
(
mem_sync
.
SARAM
)
mem_sync
.
SARAM
->
ad_arm
++
;
if
(
mem_sync
.
SDRAM
)
mem_sync
.
SDRAM
->
ad_arm
++
;
}
/*
* dsp_mem_sync_config() is called from mbx1 workqueue
*/
int
dsp_mem_sync_config
(
struct
mem_sync_struct
*
sync
)
{
size_t
sync_seq_sz
=
sizeof
(
struct
sync_seq
);
#ifdef OLD_BINARY_SUPPORT
if
(
sync
==
NULL
)
{
memset
(
&
mem_sync
,
0
,
sizeof
(
struct
mem_sync_struct
));
return
0
;
}
#endif
if
((
dsp_mem_type
(
sync
->
DARAM
,
sync_seq_sz
)
!=
MEM_TYPE_DARAM
)
||
(
dsp_mem_type
(
sync
->
SARAM
,
sync_seq_sz
)
!=
MEM_TYPE_SARAM
)
||
(
dsp_mem_type
(
sync
->
SDRAM
,
sync_seq_sz
)
!=
MEM_TYPE_EXTERN
))
{
printk
(
KERN_ERR
"omapdsp: mem_sync address validation failure!
\n
"
" mem_sync.DARAM = 0x%p,
\n
"
" mem_sync.SARAM = 0x%p,
\n
"
" mem_sync.SDRAM = 0x%p,
\n
"
,
sync
->
DARAM
,
sync
->
SARAM
,
sync
->
SDRAM
);
return
-
1
;
}
memcpy
(
&
mem_sync
,
sync
,
sizeof
(
struct
mem_sync_struct
));
return
0
;
}
/*
* kmem_reserve(), kmem_release():
* reserve or release kernel memory for exmap().
...
...
@@ -262,11 +307,21 @@ static unsigned long dsp_mem_get_dma_pages(unsigned int order)
return
__get_dma_pages
(
GFP_KERNEL
,
order
);
}
static
void
dsp_mem_free_pages
(
unsigned
int
buf
,
unsigned
int
order
)
static
void
dsp_mem_free_pages
(
unsigned
long
buf
,
unsigned
int
order
)
{
struct
kmem_pool
*
pool
;
struct
page
*
page
,
*
ps
,
*
pe
;
int
i
;
ps
=
virt_to_page
(
buf
);
pe
=
virt_to_page
(
buf
+
(
1
<<
(
PAGE_SHIFT
+
order
)));
for
(
page
=
ps
;
page
<
pe
;
page
++
)
{
ClearPageReserved
(
page
);
}
/*
* return buffer to kmem_pool or paging system
*/
switch
(
order
)
{
case
ORDER_1MB
:
pool
=
&
kmem_pool_1M
;
...
...
@@ -358,6 +413,7 @@ static void exmap_clear_armmmu(unsigned long virt, unsigned long size)
static
int
exmap_valid
(
void
*
vadr
,
size_t
len
)
{
/* exmap_sem should be held before calling this function */
int
i
;
start:
...
...
@@ -389,6 +445,107 @@ start:
return
0
;
}
enum
dsp_mem_type_e
dsp_mem_type
(
void
*
vadr
,
size_t
len
)
{
void
*
ds
=
(
void
*
)
daram_base
;
void
*
de
=
(
void
*
)
daram_base
+
daram_size
;
void
*
ss
=
(
void
*
)
saram_base
;
void
*
se
=
(
void
*
)
saram_base
+
saram_size
;
int
ret
;
if
((
vadr
>=
ds
)
&&
(
vadr
<
de
))
{
if
(
vadr
+
len
>
de
)
return
MEM_TYPE_CROSSING
;
else
return
MEM_TYPE_DARAM
;
}
else
if
((
vadr
>=
ss
)
&&
(
vadr
<
se
))
{
if
(
vadr
+
len
>
se
)
return
MEM_TYPE_CROSSING
;
else
return
MEM_TYPE_SARAM
;
}
else
{
down_read
(
&
exmap_sem
);
if
(
exmap_valid
(
vadr
,
len
))
ret
=
MEM_TYPE_EXTERN
;
else
ret
=
MEM_TYPE_NONE
;
up_read
(
&
exmap_sem
);
return
ret
;
}
}
int
dsp_address_validate
(
void
*
p
,
size_t
len
,
char
*
fmt
,
...)
{
if
(
dsp_mem_type
(
p
,
len
)
<=
0
)
{
if
(
fmt
!=
NULL
)
{
char
s
[
64
];
va_list
args
;
va_start
(
args
,
fmt
);
vsprintf
(
s
,
fmt
,
args
);
va_end
(
args
);
printk
(
KERN_ERR
"omapdsp: %s address(0x%p) and size(0x%x) is "
"not valid!
\n
"
" (crossing different type of memories, or
\n
"
" external memory space where no "
"actual memory is mapped)
\n
"
,
s
,
p
,
len
);
}
return
-
1
;
}
return
0
;
}
/*
* exmap_use(), unuse():
* when the mapped area is exported to user space with mmap,
* the usecount is incremented.
* while the usecount > 0, that area can't be released.
*/
void
exmap_use
(
void
*
vadr
,
size_t
len
)
{
int
i
;
down_write
(
&
exmap_sem
);
for
(
i
=
0
;
i
<
DSPMMU_TLB_LINES
;
i
++
)
{
void
*
mapadr
;
unsigned
long
mapsize
;
struct
exmap_tbl
*
ent
=
&
exmap_tbl
[
i
];
if
(
!
ent
->
valid
)
continue
;
mapadr
=
(
void
*
)
ent
->
vadr
;
mapsize
=
1
<<
(
ent
->
order
+
PAGE_SHIFT
);
if
((
vadr
+
len
>
mapadr
)
&&
(
vadr
<
mapadr
+
mapsize
))
{
ent
->
usecount
++
;
}
}
up_write
(
&
exmap_sem
);
}
void
exmap_unuse
(
void
*
vadr
,
size_t
len
)
{
int
i
;
down_write
(
&
exmap_sem
);
for
(
i
=
0
;
i
<
DSPMMU_TLB_LINES
;
i
++
)
{
void
*
mapadr
;
unsigned
long
mapsize
;
struct
exmap_tbl
*
ent
=
&
exmap_tbl
[
i
];
if
(
!
ent
->
valid
)
continue
;
mapadr
=
(
void
*
)
ent
->
vadr
;
mapsize
=
1
<<
(
ent
->
order
+
PAGE_SHIFT
);
if
((
vadr
+
len
>
mapadr
)
&&
(
vadr
<
mapadr
+
mapsize
))
{
ent
->
usecount
--
;
}
}
up_write
(
&
exmap_sem
);
}
/*
* dsp_virt_to_phys()
* returns physical address, and sets len to valid length
...
...
@@ -744,12 +901,13 @@ found_free:
goto
fail
;
}
exmap_ent
->
buf
=
buf
;
exmap_ent
->
vadr
=
_vadr
;
exmap_ent
->
order
=
order
;
exmap_ent
->
valid
=
1
;
exmap_ent
->
cntnu
=
cntnu
;
exmap_ent
->
type
=
type
;
exmap_ent
->
buf
=
buf
;
exmap_ent
->
vadr
=
_vadr
;
exmap_ent
->
order
=
order
;
exmap_ent
->
valid
=
1
;
exmap_ent
->
cntnu
=
cntnu
;
exmap_ent
->
type
=
type
;
exmap_ent
->
usecount
=
0
;
if
((
_size
-=
unit
)
==
0
)
{
/* normal completion */
up_write
(
&
exmap_sem
);
...
...
@@ -812,6 +970,14 @@ static int dsp_exunmap(unsigned long dspadr)
return
-
EINVAL
;
found_map:
if
(
ent
->
usecount
>
0
)
{
printk
(
KERN_ERR
"omapdsp: exmap reference count is not 0.
\n
"
" idx=%d, vadr=%p, order=%d, usecount=%d
\n
"
,
idx
,
ent
->
vadr
,
ent
->
order
,
ent
->
usecount
);
up_write
(
&
exmap_sem
);
return
-
EINVAL
;
}
/* clearing DSP TLB entry */
dsp_mmu_clear_tlb
(
dspadr
);
...
...
@@ -871,11 +1037,6 @@ static void exmap_flush(void)
/* flush TLB */
flush_tlb_kernel_range
(
dspmem_base
+
dspmem_size
,
dspmem_base
+
DSPSPACE_SIZE
);
/*
* we should clear processes' mm as well,
* because processes might had accessed to those spaces
* with old table in the past.
*/
up_write
(
&
exmap_sem
);
}
...
...
@@ -998,11 +1159,12 @@ static void dsp_mmu_init(void)
phys
=
__pa
(
dspvect_page
);
virt
=
dspbyte_to_virt
(
DSP_INIT_PAGE
);
/* 0xe0fff000 */
exmap_set_armmmu
((
unsigned
long
)
virt
,
phys
,
PAGE_SIZE
);
exmap_tbl
[
0
].
buf
=
dspvect_page
;
exmap_tbl
[
0
].
vadr
=
virt
;
exmap_tbl
[
0
].
order
=
0
;
exmap_tbl
[
0
].
valid
=
1
;
exmap_tbl
[
0
].
cntnu
=
0
;
exmap_tbl
[
0
].
buf
=
dspvect_page
;
exmap_tbl
[
0
].
vadr
=
virt
;
exmap_tbl
[
0
].
usecount
=
0
;
exmap_tbl
[
0
].
order
=
0
;
exmap_tbl
[
0
].
valid
=
1
;
exmap_tbl
[
0
].
cntnu
=
0
;
/* DSP TLB initialization */
set_tlb_lock
(
0
,
0
);
...
...
@@ -1020,88 +1182,66 @@ static void dsp_mmu_shutdown(void)
}
/*
*
dsp_
mem_enable() / disable():
*
int
mem_enable() / disable():
* if the address is in DSP internal memories,
* we send PM mailbox commands so that DSP DMA domain won't go in idle
* when ARM is accessing to those memories.
* if the address is in external memory, acquire exmap_sem.
*
* __dsp_mem_enable() / disable() should be called only from __dsp_mbsend().
*/
static
int
dsp_mem_en_count
;
int
dsp_mem_enable
(
void
*
adr
)
static
int
intmem_enable
(
void
)
{
struct
mbcmd
mb
;
int
ret
;
int
ret
=
0
;
if
(
is_dsp_internal_mem
(
adr
))
{
if
(
dsp_is_ready
()
&&
(
!
dsp_mem_en_count
)
&&
(
dsp_icrmask
&
DSPREG_ICR_DMA_IDLE_DOMAIN
))
{
mbcmd_set
(
mb
,
MBCMD
(
PM
),
OMAP_DSP_MBCMD_PM_ENABLE
,
DSPREG_ICR_DMA_IDLE_DOMAIN
);
if
((
ret
=
dsp_mbsend
(
&
mb
))
<
0
)
return
ret
;
dsp_mem_en_count
++
;
}
}
else
down_read
(
&
exmap_sem
);
return
0
;
}
if
(
dsp_is_ready
())
ret
=
dsp_mbsend
(
MBCMD
(
PM
),
OMAP_DSP_MBCMD_PM_ENABLE
,
DSPREG_ICR_DMA_IDLE_DOMAIN
);
int
dsp_mem_disable
(
void
*
adr
)
{
struct
mbcmd
mb
;
int
ret
;
return
ret
;
}
if
(
is_dsp_internal_mem
(
adr
))
{
if
(
dsp_is_ready
()
&&
dsp_mem_en_count
)
{
mbcmd_set
(
mb
,
MBCMD
(
PM
),
OMAP_DSP_MBCMD_PM_DISABLE
,
DSPREG_ICR_DMA_IDLE_DOMAIN
);
if
((
ret
=
dsp_mbsend
(
&
mb
))
<
0
)
return
ret
;
dsp_mem_en_count
--
;
}
}
else
up_read
(
&
exmap_sem
);
return
0
;
static
void
intmem_disable
(
void
)
{
if
(
dsp_is_ready
())
dsp_mbsend
(
MBCMD
(
PM
),
OMAP_DSP_MBCMD_PM_DISABLE
,
DSPREG_ICR_DMA_IDLE_DOMAIN
);
}
int
__dsp_mem_enable
(
void
*
adr
)
/*
* dsp_mem_enable() / disable()
*/
int
intmem_usecount
;
int
dsp_mem_enable
(
void
*
adr
)
{
struct
mbcmd
mb
;
int
ret
;
int
ret
=
0
;
if
(
is_dsp_internal_mem
(
adr
))
{
if
(
dsp_is_ready
()
&&
(
!
dsp_mem_en_count
)
&&
(
dsp_icrmask
&
DSPREG_ICR_DMA_IDLE_DOMAIN
))
{
mbcmd_set
(
mb
,
MBCMD
(
PM
),
OMAP_DSP_MBCMD_PM_ENABLE
,
DSPREG_ICR_DMA_IDLE_DOMAIN
);
if
((
ret
=
__mbsend
(
&
mb
))
<
0
)
return
ret
;
dsp_mem_en_count
++
;
}
if
(
intmem_usecount
++
==
0
)
ret
=
omap_dsp_request_mem
();
}
else
down_read
(
&
exmap_sem
);
return
0
;
return
ret
;
}
int
__
dsp_mem_disable
(
void
*
adr
)
void
dsp_mem_disable
(
void
*
adr
)
{
struct
mbcmd
mb
;
int
ret
;
if
(
is_dsp_internal_mem
(
adr
))
{
if
(
dsp_is_ready
()
&&
dsp_mem_en_count
)
{
mbcmd_set
(
mb
,
MBCMD
(
PM
),
OMAP_DSP_MBCMD_PM_DISABLE
,
DSPREG_ICR_DMA_IDLE_DOMAIN
);
if
((
ret
=
__mbsend
(
&
mb
))
<
0
)
return
ret
;
dsp_mem_en_count
--
;
}
if
(
--
intmem_usecount
==
0
)
omap_dsp_release_mem
();
}
else
up_read
(
&
exmap_sem
);
return
0
;
}
/* for safety */
void
dsp_mem_usecount_clear
(
void
)
{
if
(
intmem_usecount
!=
0
)
{
printk
(
KERN_WARNING
"omapdsp: unbalanced memory request/release detected.
\n
"
" intmem_usecount is not zero at where "
"it should be! ... fixed to be zero.
\n
"
);
intmem_usecount
=
0
;
omap_dsp_release_mem
();
}
}
/*
...
...
@@ -1144,10 +1284,10 @@ static ssize_t intmem_read(struct file *file, char *buf, size_t count,
read
=
size
-
p
;
if
(
copy_to_user
(
buf
,
vadr
,
read
))
{
read
=
-
EFAULT
;
goto
finish
;
goto
out
;
}
*
ppos
+=
read
;
finish
:
out
:
clk_unuse
(
api_ck_handle
);
return
read
;
}
...
...
@@ -1157,39 +1297,37 @@ static ssize_t exmem_read(struct file *file, char *buf, size_t count,
{
unsigned
long
p
=
*
ppos
;
void
*
vadr
=
dspbyte_to_virt
(
p
);
ssize_t
ret
;
down_read
(
&
exmap_sem
);
if
(
!
exmap_valid
(
vadr
,
count
))
{
printk
(
KERN_ERR
"omapdsp: DSP address %08lx / size %08x "
"is not valid!
\n
"
,
p
,
count
);
ret
=
-
EFAULT
;
goto
up_out
;
return
-
EFAULT
;
}
if
(
count
>
DSPSPACE_SIZE
-
p
)
count
=
DSPSPACE_SIZE
-
p
;
if
(
copy_to_user
(
buf
,
vadr
,
count
))
{
ret
=
-
EFAULT
;
goto
up_out
;
}
if
(
copy_to_user
(
buf
,
vadr
,
count
))
return
-
EFAULT
;
*
ppos
+=
count
;
up_read
(
&
exmap_sem
);
return
count
;
up_out:
up_read
(
&
exmap_sem
);
return
ret
;
}
static
ssize_t
dsp_mem_read
(
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
int
ret
;
void
*
vadr
=
dspbyte_to_virt
(
*
(
unsigned
long
*
)
ppos
);
if
(
dsp_mem_enable
(
vadr
)
<
0
)
return
-
EBUSY
;
if
(
is_dspbyte_internal_mem
(
*
ppos
))
ret
urn
intmem_read
(
file
,
buf
,
count
,
ppos
);
ret
=
intmem_read
(
file
,
buf
,
count
,
ppos
);
else
return
exmem_read
(
file
,
buf
,
count
,
ppos
);
ret
=
exmem_read
(
file
,
buf
,
count
,
ppos
);
dsp_mem_disable
(
vadr
);
return
ret
;
}
static
ssize_t
intmem_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
...
...
@@ -1208,10 +1346,10 @@ static ssize_t intmem_write(struct file *file, const char *buf, size_t count,
written
=
size
-
p
;
if
(
copy_from_user
(
vadr
,
buf
,
written
))
{
written
=
-
EFAULT
;
goto
finish
;
goto
out
;
}
*
ppos
+=
written
;
finish
:
out
:
clk_unuse
(
api_ck_handle
);
return
written
;
}
...
...
@@ -1221,39 +1359,37 @@ static ssize_t exmem_write(struct file *file, const char *buf, size_t count,
{
unsigned
long
p
=
*
ppos
;
void
*
vadr
=
dspbyte_to_virt
(
p
);
ssize_t
ret
;
down_read
(
&
exmap_sem
);
if
(
!
exmap_valid
(
vadr
,
count
))
{
printk
(
KERN_ERR
"omapdsp: DSP address %08lx / size %08x "
"is not valid!
\n
"
,
p
,
count
);
ret
=
-
EFAULT
;
goto
up_out
;
return
-
EFAULT
;
}
if
(
count
>
DSPSPACE_SIZE
-
p
)
count
=
DSPSPACE_SIZE
-
p
;
if
(
copy_from_user
(
vadr
,
buf
,
count
))
{
ret
=
-
EFAULT
;
goto
up_out
;
}
if
(
copy_from_user
(
vadr
,
buf
,
count
))
return
-
EFAULT
;
*
ppos
+=
count
;
up_read
(
&
exmap_sem
);
return
count
;
up_out:
up_read
(
&
exmap_sem
);
return
ret
;
}
static
ssize_t
dsp_mem_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
int
ret
;
void
*
vadr
=
dspbyte_to_virt
(
*
(
unsigned
long
*
)
ppos
);
if
(
dsp_mem_enable
(
vadr
)
<
0
)
return
-
EBUSY
;
if
(
is_dspbyte_internal_mem
(
*
ppos
))
ret
urn
intmem_write
(
file
,
buf
,
count
,
ppos
);
ret
=
intmem_write
(
file
,
buf
,
count
,
ppos
);
else
return
exmem_write
(
file
,
buf
,
count
,
ppos
);
ret
=
exmem_write
(
file
,
buf
,
count
,
ppos
);
dsp_mem_disable
(
vadr
);
return
ret
;
}
static
int
dsp_mem_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
...
...
@@ -1325,15 +1461,12 @@ static int dsp_mem_open(struct inode *inode, struct file *file)
{
if
(
!
capable
(
CAP_SYS_RAWIO
))
return
-
EPERM
;
if
(
dsp_mem_enable
((
void
*
)
dspmem_base
)
<
0
)
return
-
EBUSY
;
return
0
;
}
static
int
dsp_mem_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
dsp_mem_disable
((
void
*
)
dspmem_base
);
return
0
;
}
...
...
@@ -1414,16 +1547,16 @@ static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
down_read
(
&
exmap_sem
);
len
=
sprintf
(
buf
,
"v: valid, c: cntnu
\n
"
"ety vadr buf od
\n
"
);
"ety vadr buf od
uc
\n
"
);
/* 00: v c 0xe0300000 0xc0171800 0 */
for
(
i
=
0
;
i
<
DSPMMU_TLB_LINES
;
i
++
)
{
struct
exmap_tbl
*
ent
=
&
exmap_tbl
[
i
];
/* 00: v c 0xe0300000 0xc0171800 0 */
len
+=
sprintf
(
buf
+
len
,
"%02d: %c %c 0x%8p 0x%8p %2d
\n
"
,
len
+=
sprintf
(
buf
+
len
,
"%02d: %c %c 0x%8p 0x%8p %2d
%2d
\n
"
,
i
,
ent
->
valid
?
'v'
:
' '
,
ent
->
cntnu
?
'c'
:
' '
,
ent
->
vadr
,
ent
->
buf
,
ent
->
order
);
ent
->
vadr
,
ent
->
buf
,
ent
->
order
,
ent
->
usecount
);
}
up_read
(
&
exmap_sem
);
...
...
@@ -1432,6 +1565,19 @@ static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
static
struct
device_attribute
dev_attr_exmap
=
__ATTR_RO
(
exmap
);
static
ssize_t
kmem_pool_show
(
struct
device
*
dev
,
char
*
buf
)
{
int
count_1M
,
count_64K
,
total
;
count_1M
=
kmem_pool_1M
.
count
;
count_64K
=
kmem_pool_64K
.
count
;
total
=
count_1M
*
SZ_1MB
+
count_64K
*
SZ_64KB
;
return
sprintf
(
buf
,
"0x%x %d %d
\n
"
,
total
,
count_1M
,
count_64K
);
}
static
struct
device_attribute
dev_attr_kmem_pool
=
__ATTR_RO
(
kmem_pool
);
/*
* DSP MMU interrupt handler
*/
...
...
@@ -1516,9 +1662,11 @@ irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* FIXME */
dsp_err_mmu_set
(
dsp_fault_adr
);
}
else
{
disable_irq
(
INT_DSP_MMU
);
__dsp_mmu_itack
();
printk
(
KERN_INFO
"Resetting DSP...
\n
"
);
__dsp_reset
(
);
clk_unuse
(
api_ck_handle
);
dsp_cpustat_request
(
CPUSTAT_RESET
);
enable_irq
(
INT_DSP_MMU
);
/*
* if we enable followings, semaphore lock should be avoided.
*
...
...
@@ -1547,7 +1695,13 @@ struct file_operations dsp_mem_fops = {
void
dsp_mem_start
(
void
)
{
dsp_mem_en_count
=
0
;
dsp_register_mem_cb
(
intmem_enable
,
intmem_disable
);
}
void
dsp_mem_stop
(
void
)
{
memset
(
&
mem_sync
,
0
,
sizeof
(
struct
mem_sync_struct
));
dsp_unregister_mem_cb
();
}
int
__init
dsp_mem_init
(
void
)
...
...
@@ -1570,6 +1724,7 @@ int __init dsp_mem_init(void)
device_create_file
(
&
dsp_device
.
dev
,
&
dev_attr_mmu
);
device_create_file
(
&
dsp_device
.
dev
,
&
dev_attr_exmap
);
device_create_file
(
&
dsp_device
.
dev
,
&
dev_attr_kmem_pool
);
return
0
;
}
...
...
@@ -1581,19 +1736,18 @@ void dsp_mem_exit(void)
if
(
dspvect_page
!=
NULL
)
{
unsigned
long
virt
;
pmd_t
*
pmdp
;
pte_t
*
ptep
;
down_read
(
&
exmap_sem
);
virt
=
(
unsigned
long
)
dspbyte_to_virt
(
DSP_INIT_PAGE
);
flush_tlb_kernel_range
(
virt
,
virt
+
PAGE_SIZE
);
free_page
((
unsigned
long
)
dspvect_page
);
dspvect_page
=
NULL
;
virt
=
(
unsigned
long
)
dspbyte_to_virt
(
DSP_INIT_PAGE
);
pmdp
=
pmd_offset
(
pgd_offset_k
(
virt
),
virt
);
ptep
=
pte_offset_kernel
(
pmdp
,
0
);
pmd_clear
(
pmdp
);
pte_free_kernel
(
ptep
);
up_read
(
&
exmap_sem
);
}
device_remove_file
(
&
dsp_device
.
dev
,
&
dev_attr_mmu
);
device_remove_file
(
&
dsp_device
.
dev
,
&
dev_attr_exmap
);
device_remove_file
(
&
dsp_device
.
dev
,
&
dev_attr_kmem_pool
);
}
arch/arm/plat-omap/dsp/error.c
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 200
4/11/22: DSP Gateway version 3.2
* 200
5/03/11: DSP Gateway version 3.3
*/
#include <linux/module.h>
...
...
@@ -138,15 +138,22 @@ int dsp_err_wdt_isset(void)
/*
* functions called from mailbox1 interrupt routine
*/
void
mbx1_wdt
(
struct
mbcmd
*
mb
)
static
void
mbx1_err_wdt
(
unsigned
short
data
)
{
printk
(
KERN_WARNING
"omapdsp: DSP WDT expired!
\n
"
);
errcode
|=
OMAP_DSP_ERRDT_WDT
;
errcnt
++
;
wdtval
=
mb
->
data
;
wdtval
=
data
;
wake_up_interruptible
(
&
err_wait_q
);
}
#ifdef OLD_BINARY_SUPPORT
/* v3.3 obsolete */
void
mbx1_wdt
(
struct
mbcmd
*
mb
)
{
mbx1_err_wdt
(
mb
->
data
);
}
#endif
extern
void
mbx1_err_ipbfull
(
void
);
extern
void
mbx1_err_fatal
(
unsigned
char
tid
);
...
...
@@ -174,6 +181,10 @@ void mbx1_err(struct mbcmd *mb)
tid
=
mb
->
data
&
0x00ff
;
mbx1_err_fatal
(
tid
);
break
;
case
OMAP_DSP_EID_WDT
:
mbx1_err_wdt
(
mb
->
data
);
break
;
}
}
...
...
arch/arm/plat-omap/dsp/fifo.h
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2005/02/24: DSP Gateway version 3.
2
* 2005/02/24: DSP Gateway version 3.
3
*/
struct
fifo_struct
{
...
...
arch/arm/plat-omap/dsp/hardware_dsp.h
View file @
b3ddf280
...
...
@@ -21,12 +21,25 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 200
4/09/30: DSP Gateway version 3.2
* 200
5/05/30: DSP Gateway version 3.3
*/
#ifndef __OMAP_DSP_HARDWARE_DSP_H
#define __OMAP_DSP_HARDWARE_DSP_H
#ifdef CONFIG_ARCH_OMAP1510
#define OMAP1510_DARAM_BASE 0xe0000000
#define OMAP1510_DARAM_SIZE 0x10000
#define OMAP1510_SARAM_BASE 0xe0010000
#define OMAP1510_SARAM_SIZE 0x18000
#endif
#ifdef CONFIG_ARCH_OMAP16XX
#define OMAP16XX_DARAM_BASE 0xe0000000
#define OMAP16XX_DARAM_SIZE 0x10000
#define OMAP16XX_SARAM_BASE 0xe0010000
#define OMAP16XX_SARAM_SIZE 0x18000
#endif
/*
* MAJOR device number: !! allocated arbitrary !!
*/
...
...
@@ -186,6 +199,7 @@
/*
* DSP ICR
*/
#define DSPREG_ICR_RESERVED_BITS 0xffc0
#define DSPREG_ICR_EMIF_IDLE_DOMAIN 0x0020
#define DSPREG_ICR_DPLL_IDLE_DOMAIN 0x0010
#define DSPREG_ICR_PER_IDLE_DOMAIN 0x0008
...
...
arch/arm/plat-omap/dsp/ipbuf.c
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2005/0
2/17: DSP Gateway version 3.2
* 2005/0
6/06: DSP Gateway version 3.3
*/
#include <linux/init.h>
...
...
@@ -38,51 +38,51 @@ struct ipbuf **ipbuf;
struct
ipbcfg
ipbcfg
;
struct
ipbuf_sys
*
ipbuf_sys_da
,
*
ipbuf_sys_ad
;
static
struct
ipblink
ipb_free
=
IPBLINK_INIT
;
static
int
ipbuf_sys_hold_mem_active
;
void
ipbuf_stop
(
void
)
{
int
i
;
spin_lock
(
&
ipb_free
.
lock
);
INIT_IPBLINK
(
&
ipb_free
);
spin_unlock
(
&
ipb_free
.
lock
);
ipbcfg
.
ln
=
0
;
if
(
ipbuf
)
{
kfree
(
ipbuf
);
ipbuf
=
NULL
;
}
for
(
i
=
0
;
i
<
ipbuf_sys_hold_mem_active
;
i
++
)
{
dsp_mem_disable
((
void
*
)
daram_base
);
}
ipbuf_sys_hold_mem_active
=
0
;
}
/*
* ipbuf_config() is called by mailbox workqueue
*/
int
ipbuf_config
(
unsigned
short
ln
,
unsigned
short
lsz
,
unsigned
long
adr
)
int
ipbuf_config
(
unsigned
short
ln
,
unsigned
short
lsz
,
void
*
base
)
{
void
*
base
;
unsigned
long
lsz_byte
=
((
unsigned
long
)
lsz
)
<<
1
;
size_t
size
;
int
ret
=
0
;
int
i
;
spin_lock
(
&
ipb_free
.
lock
);
INIT_IPBLINK
(
&
ipb_free
);
spin_unlock
(
&
ipb_free
.
lock
);
/*
* global IPBUF
*/
if
(
adr
&
0x1
)
{
if
(
((
unsigned
long
)
base
)
&
0x3
)
{
printk
(
KERN_ERR
"
mbx: global ipbuf address (0x%08lx) is odd number!
\n
"
,
adr
);
"
omapdsp: global ipbuf address(0x%p) is not "
"32-bit aligned!
\n
"
,
base
);
return
-
EINVAL
;
}
size
=
lsz_byte
*
ln
;
if
(
adr
+
size
>
DSPSPACE_SIZE
)
{
printk
(
KERN_ERR
"mbx: ipbuf address (0x%08lx) and size (0x%08x) is "
"illegal!
\n
"
,
adr
,
size
);
if
(
dsp_address_validate
(
base
,
size
,
"global ipbuf"
)
<
0
)
return
-
EINVAL
;
}
base
=
dspword_to_virt
(
adr
);
ipbuf
=
kmalloc
(
sizeof
(
void
*
)
*
ln
,
GFP_KERNEL
);
if
(
ipbuf
==
NULL
)
{
printk
(
KERN_ERR
"mbx: memory allocation for ipbuf failed.
\n
"
);
printk
(
KERN_ERR
"omapdsp: memory allocation for ipbuf failed.
\n
"
);
return
-
ENOMEM
;
}
for
(
i
=
0
;
i
<
ln
;
i
++
)
{
...
...
@@ -101,20 +101,75 @@ int ipbuf_config(unsigned short ln, unsigned short lsz, unsigned long adr)
"omapdsp: ipbuf[%d] crosses 64k-word boundary!
\n
"
" @0x%p, size=0x%08lx
\n
"
,
i
,
top
,
lsz_byte
);
ret
=
-
EINVAL
;
goto
free_out
;
}
}
ipbcfg
.
ln
=
ln
;
ipbcfg
.
lsz
=
lsz
;
ipbcfg
.
adr
=
adr
;
ipbcfg
.
base
=
base
;
ipbcfg
.
bsycnt
=
ln
;
/* DSP holds all ipbufs initially. */
ipbcfg
.
cnt_full
=
0
;
printk
(
KERN_INFO
"omapdsp: IPBUF configuration
\n
"
" %d words * %d lines at 0x%p.
\n
"
,
ipbcfg
.
lsz
,
ipbcfg
.
ln
,
dspword_to_virt
(
ipbcfg
.
adr
)
);
ipbcfg
.
lsz
,
ipbcfg
.
ln
,
ipbcfg
.
base
);
return
ret
;
free_out:
kfree
(
ipbuf
);
ipbuf
=
NULL
;
return
ret
;
}
int
ipbuf_sys_config
(
void
*
p
,
enum
arm_dsp_dir
dir
)
{
char
*
dir_str
=
(
dir
==
DIR_D2A
)
?
"D2A"
:
"A2D"
;
if
(((
unsigned
long
)
p
)
&
0x3
)
{
printk
(
KERN_ERR
"omapdsp: system ipbuf(%s) address(0x%p) is "
"not 32-bit aligned!
\n
"
,
dir_str
,
p
);
return
-
1
;
}
if
(
dsp_address_validate
(
p
,
sizeof
(
struct
ipbuf_sys
),
"system ipbuf(%s)"
,
dir_str
)
<
0
)
return
-
1
;
if
(
dsp_mem_type
(
p
,
sizeof
(
struct
ipbuf_sys
))
!=
MEM_TYPE_EXTERN
)
{
printk
(
KERN_WARNING
"omapdsp: system ipbuf(%s) is placed in"
" DSP internal memory.
\n
"
" It will prevent DSP from idling.
\n
"
,
dir_str
);
ipbuf_sys_hold_mem_active
++
;
/*
* dsp_mem_enable() never fails because
* it has been already enabled in dspcfg process and
* this will just increment the usecount.
*/
dsp_mem_enable
((
void
*
)
daram_base
);
}
if
(
dir
==
DIR_D2A
)
ipbuf_sys_da
=
p
;
else
ipbuf_sys_ad
=
p
;
return
0
;
}
int
ipbuf_p_validate
(
void
*
p
,
enum
arm_dsp_dir
dir
)
{
char
*
dir_str
=
(
dir
==
DIR_D2A
)
?
"D2A"
:
"A2D"
;
if
(((
unsigned
long
)
p
)
&
0x3
)
{
printk
(
KERN_ERR
"omapdsp: private ipbuf(%s) address(0x%p) is "
"not 32-bit aligned!
\n
"
,
dir_str
,
p
);
return
-
1
;
}
return
dsp_address_validate
(
p
,
sizeof
(
struct
ipbuf_p
),
"private ipbuf(%s)"
,
dir_str
);
}
/*
...
...
@@ -124,19 +179,22 @@ unsigned short get_free_ipbuf(unsigned char tid)
{
unsigned
short
bid
;
if
(
ipblink_empty
(
&
ipb_free
))
{
/* FIXME: wait on queue when not available. */
if
(
dsp_mem_enable_ipbuf
()
<
0
)
return
OMAP_DSP_BID_NULL
;
}
/*
* FIXME: dsp_enable_dspmem!
*/
spin_lock
(
&
ipb_free
.
lock
);
if
(
ipblink_empty
(
&
ipb_free
))
{
/* FIXME: wait on queue when not available. */
bid
=
OMAP_DSP_BID_NULL
;
goto
out
;
}
bid
=
ipb_free
.
top
;
ipbuf
[
bid
]
->
la
=
tid
;
/* lock */
ipblink_del_top
(
&
ipb_free
,
ipbuf
);
out:
spin_unlock
(
&
ipb_free
.
lock
);
dsp_mem_disable_ipbuf
();
return
bid
;
}
...
...
@@ -161,12 +219,10 @@ void release_ipbuf(unsigned short bid)
static
int
try_yld
(
unsigned
short
bid
)
{
struct
mbcmd
mb
;
int
status
;
ipbuf
[
bid
]
->
sa
=
OMAP_DSP_TID_ANON
;
mbcmd_set
(
mb
,
MBCMD
(
BKYLD
),
0
,
bid
);
status
=
dsp_mbsend
(
&
mb
);
status
=
dsp_mbsend
(
MBCMD
(
BKYLD
),
0
,
bid
);
if
(
status
<
0
)
{
/* DSP is busy and ARM keeps this line. */
release_ipbuf
(
bid
);
...
...
arch/arm/plat-omap/dsp/ipbuf.h
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2005/0
2/17: DSP Gateway version 3.2
* 2005/0
5/17: DSP Gateway version 3.3
*/
struct
ipbuf
{
...
...
@@ -43,13 +43,13 @@ struct ipbuf_p {
struct
ipbuf_sys
{
unsigned
short
s
;
/* sync word */
unsigned
short
d
[
15
];
/* data */
unsigned
short
d
[
31
];
/* data */
};
struct
ipbcfg
{
unsigned
short
ln
;
unsigned
short
lsz
;
unsigned
long
adr
;
void
*
base
;
unsigned
short
bsycnt
;
unsigned
long
cnt_full
;
/* count of IPBFULL error */
};
...
...
@@ -72,8 +72,8 @@ extern struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
enable_irq(INT_D2A_MB1); \
} while(0)
#define dsp_mem_enable_ipbuf() dsp_mem_enable(
dspword_to_virt(ipbcfg.adr)
)
#define dsp_mem_disable_ipbuf() dsp_mem_disable(
dspword_to_virt(ipbcfg.adr)
)
#define dsp_mem_enable_ipbuf() dsp_mem_enable(
ipbcfg.base
)
#define dsp_mem_disable_ipbuf() dsp_mem_disable(
ipbcfg.base
)
struct
ipblink
{
spinlock_t
lock
;
...
...
@@ -89,6 +89,7 @@ struct ipblink {
#define INIT_IPBLINK(link) \
do { \
spin_lock_init(&(link)->lock); \
(link)->top = OMAP_DSP_BID_NULL; \
(link)->tail = OMAP_DSP_BID_NULL; \
} while(0)
...
...
arch/arm/plat-omap/dsp/mblog.c
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2005/0
2/17: DSP Gateway version 3.2
* 2005/0
5/18: DSP Gateway version 3.3
*/
#include <linux/module.h>
...
...
@@ -98,6 +98,7 @@ char *subcmd_name(struct mbcmd *mb)
(
cmd_l
==
EID
(
BADTCTL
))
?
"BADTCTL"
:
(
cmd_l
==
EID
(
BADPARAM
))
?
"BADPARAM"
:
(
cmd_l
==
EID
(
FATAL
))
?
"FATAL"
:
(
cmd_l
==
EID
(
WDT
))
?
"WDT"
:
(
cmd_l
==
EID
(
NOMEM
))
?
"NOMEM"
:
(
cmd_l
==
EID
(
NORES
))
?
"NORES"
:
(
cmd_l
==
EID
(
IPBFULL
))
?
"IPBFULL"
:
...
...
@@ -124,7 +125,7 @@ struct mblogent {
unsigned
long
jiffies
;
unsigned
short
cmd
;
unsigned
short
data
;
enum
mblog
_dir
dir
;
enum
arm_dsp
_dir
dir
;
};
static
struct
{
...
...
@@ -134,7 +135,7 @@ static struct {
struct
mblogent
ent
[
MBLOG_DEPTH
];
}
mblog
;
void
mblog_add
(
struct
mbcmd
*
mb
,
enum
mblog
_dir
dir
)
void
mblog_add
(
struct
mbcmd
*
mb
,
enum
arm_dsp
_dir
dir
)
{
struct
mbcmd_hw
*
mb_hw
=
(
struct
mbcmd_hw
*
)
mb
;
struct
mblogent
*
ent
;
...
...
@@ -148,11 +149,11 @@ void mblog_add(struct mbcmd *mb, enum mblog_dir dir)
if
(
mblog
.
cnt
<
0xffffffff
)
mblog
.
cnt
++
;
switch
(
dir
)
{
case
MBLOG_DIR_A
D
:
case
DIR_A2
D
:
if
(
mblog
.
cnt_ad
<
0xffffffff
)
mblog
.
cnt_ad
++
;
break
;
case
MBLOG_DIR_D
A
:
case
DIR_D2
A
:
if
(
mblog
.
cnt_da
<
0xffffffff
)
mblog
.
cnt_da
++
;
break
;
...
...
@@ -197,7 +198,7 @@ static ssize_t mblog_show(struct device *dev, struct device_attribute *attr,
const
struct
cmdinfo
*
ci
=
cmdinfo
[
mb
.
sw
.
cmd_h
];
len
+=
sprintf
(
buf
+
len
,
(
ent
->
dir
==
MBLOG_DIR_A
D
)
?
(
ent
->
dir
==
DIR_A2
D
)
?
"%08lx %d %04x %04x "
:
"%08lx %d %04x %04x "
,
ent
->
jiffies
,
mb
.
sw
.
seq
,
ent
->
cmd
,
ent
->
data
);
...
...
@@ -230,13 +231,13 @@ done:
static
struct
device_attribute
dev_attr_mblog
=
__ATTR_RO
(
mblog
);
#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
void
mblog_printcmd
(
struct
mbcmd
*
mb
,
enum
mblog
_dir
dir
)
void
mblog_printcmd
(
struct
mbcmd
*
mb
,
enum
arm_dsp
_dir
dir
)
{
const
struct
cmdinfo
*
ci
=
cmdinfo
[
mb
->
cmd_h
];
char
*
dir_str
;
char
*
subname
;
dir_str
=
(
dir
==
MBLOG_DIR_A
D
)
?
"sending"
:
"receiving"
;
dir_str
=
(
dir
==
DIR_A2
D
)
?
"sending"
:
"receiving"
;
switch
(
ci
->
cmd_l_type
)
{
case
CMD_L_TYPE_SUBCMD
:
if
((
subname
=
subcmd_name
(
mb
))
==
NULL
)
...
...
arch/arm/plat-omap/dsp/proclist.h
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2004/11/22: DSP Gateway version 3.
2
* 2004/11/22: DSP Gateway version 3.
3
*/
struct
proc_list
{
...
...
arch/arm/plat-omap/dsp/task.c
View file @
b3ddf280
...
...
@@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2005/0
2/22: DSP Gateway version 3.2
* 2005/0
7/26: DSP Gateway version 3.3
*/
#include <linux/kernel.h>
...
...
@@ -32,7 +32,6 @@
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/device.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/mm.h>
...
...
@@ -49,16 +48,32 @@
#include "fifo.h"
#include "proclist.h"
#define is_aligned(adr,align) (!((adr)&((align)-1)))
/*
* device state machine
*
taskdev.state:
device state machine
* NOTASK: task is not attached.
* ATTACHED: task is attached.
* GARBAGE: task is detached. waiting for all processes to close this device.
* ADDREQ: requesting for tadd
* DELREQ: requesting for tdel. no process is opening this device.
* KILLREQ: requesting for tkill.
* ADDFAIL: tadd failed.
* ADDING: tadd in process.
* DELING: tdel in process.
* KILLING: tkill in process.
*/
#define devstate_name(stat) (\
((stat) & OMAP_DSP_DEVSTATE_NOTASK) ? "NOTASK" :\
((stat) & OMAP_DSP_DEVSTATE_ATTACHED) ? "ATTACHED" :\
((stat) & OMAP_DSP_DEVSTATE_GARBAGE) ? "GARBAGE" :\
((stat) & OMAP_DSP_DEVSTATE_INVALID) ? "INVALID" :\
((stat) & OMAP_DSP_DEVSTATE_ADDREQ) ? "ADDREQ" :\
((stat) & OMAP_DSP_DEVSTATE_DELREQ) ? "DELREQ" :\
((stat) & OMAP_DSP_DEVSTATE_ADDFAIL) ? "ADDFAIL" :\
((stat) & OMAP_DSP_DEVSTATE_ADDING) ? "ADDING" :\
((stat) & OMAP_DSP_DEVSTATE_DELING) ? "DELING" :\
((stat) & OMAP_DSP_DEVSTATE_KILLING) ? "KILLING" :\
"unknown")
struct
taskdev
{
struct
bus_type
*
bus
;
...
...
@@ -147,6 +162,7 @@ static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor);
static
void
taskdev_delete
(
unsigned
char
minor
);
static
void
taskdev_attach_task
(
struct
taskdev
*
dev
,
struct
dsptask
*
task
);
static
void
taskdev_detach_task
(
struct
taskdev
*
dev
);
static
int
dsp_tdel_bh
(
unsigned
char
minor
,
unsigned
short
type
);
static
ssize_t
devname_show
(
struct
device
*
d
,
struct
device_attribute
*
attr
,
char
*
buf
);
...
...
@@ -345,23 +361,27 @@ static int dsp_task_config(struct dsptask *task, unsigned char tid)
{
unsigned
short
ttyp
;
struct
mbcmd
mb
;
int
ret
;
dsptask
[
tid
]
=
task
;
task
->
tid
=
tid
;
dsptask
[
tid
]
=
task
;
/* TCFG request */
task
->
state
=
TASK_STATE_CFGREQ
;
if
(
down_interruptible
(
&
cfg_sem
))
return
-
ERESTARTSYS
;
if
(
down_interruptible
(
&
cfg_sem
))
{
ret
=
-
ERESTARTSYS
;
goto
fail_out
;
}
cfg_cmd
=
MBCMD
(
TCFG
);
mbcmd_set
(
mb
,
MBCMD
(
TCFG
),
tid
,
0
);
dsp_mbsend_and_wait
(
&
mb
,
&
cfg_wait_q
);
dsp_mb
cmd_
send_and_wait
(
&
mb
,
&
cfg_wait_q
);
cfg_cmd
=
0
;
up
(
&
cfg_sem
);
if
(
task
->
state
!=
TASK_STATE_READY
)
{
printk
(
KERN_ERR
"omapdsp: task %d configuration error!
\n
"
,
tid
);
return
-
EINVAL
;
ret
=
-
EINVAL
;
goto
fail_out
;
}
if
(
strlen
(
task
->
name
)
<=
1
)
...
...
@@ -370,35 +390,49 @@ static int dsp_task_config(struct dsptask *task, unsigned char tid)
ttyp
=
task
->
ttyp
;
/*
* task info sanity check
*/
/* task type check */
if
(
rcvtyp_psv
(
ttyp
)
&&
rcvtyp_pvt
(
ttyp
))
{
printk
(
KERN_ERR
"
mbx
: illegal task type(0x%04x), tid=%d
\n
"
,
printk
(
KERN_ERR
"
omapdsp
: illegal task type(0x%04x), tid=%d
\n
"
,
tid
,
ttyp
);
ret
=
-
EINVAL
;
goto
fail_out
;
}
/* private buffer address check */
if
(
sndtyp_pvt
(
ttyp
))
{
void
*
p
=
task
->
rcvdt
.
bk
.
ipbuf_pvt_r
;
if
((
unsigned
long
)
p
&
0x1
)
{
printk
(
KERN_ERR
"mbx: private ipbuf (DSP->ARM) address (0x%p) "
"is odd number!
\n
"
,
p
);
return
-
EINVAL
;
}
if
(
sndtyp_pvt
(
ttyp
)
&&
(
ipbuf_p_validate
(
task
->
rcvdt
.
bk
.
ipbuf_pvt_r
,
DIR_D2A
)
<
0
))
{
ret
=
-
EINVAL
;
goto
fail_out
;
}
if
(
rcvtyp_pvt
(
ttyp
))
{
void
*
p
=
task
->
ipbuf_pvt_w
;
if
((
unsigned
long
)
p
&
0x1
)
{
printk
(
KERN_ERR
"mbx: private ipbuf (ARM->DSP) address (0x%p) "
"is odd number!
\n
"
,
p
);
return
-
EINVAL
;
}
if
(
rcvtyp_pvt
(
ttyp
)
&&
(
ipbuf_p_validate
(
task
->
ipbuf_pvt_w
,
DIR_A2D
)
<
0
))
{
ret
=
-
EINVAL
;
goto
fail_out
;
}
/* mmap buffer configuration check */
if
((
task
->
map_length
>
0
)
&&
((
!
is_aligned
((
unsigned
long
)
task
->
map_base
,
PAGE_SIZE
))
||
(
!
is_aligned
(
task
->
map_length
,
PAGE_SIZE
))
||
(
dsp_mem_type
(
task
->
map_base
,
task
->
map_length
)
!=
MEM_TYPE_EXTERN
)))
{
printk
(
KERN_ERR
"omapdsp: illegal mmap buffer address(0x%p) or "
"length(0x%x).
\n
"
" It needs to be page-aligned and located at "
"external memory.
\n
"
,
task
->
map_base
,
task
->
map_length
);
ret
=
-
EINVAL
;
goto
fail_out
;
}
/*
* initialization
*/
/* read initialization */
if
(
sndtyp_wd
(
ttyp
))
{
/* word */
...
...
@@ -410,11 +444,11 @@ static int dsp_task_config(struct dsptask *task, unsigned char tid)
printk
(
KERN_ERR
"omapdsp: unable to allocate receive buffer. "
"(%d bytes for %s)
\n
"
,
fifosz
,
task
->
name
);
return
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
fail_out
;
}
}
else
{
/* block */
spin_lock_init
(
&
task
->
rcvdt
.
bk
.
link
.
lock
);
INIT_IPBLINK
(
&
task
->
rcvdt
.
bk
.
link
);
task
->
rcvdt
.
bk
.
rp
=
0
;
}
...
...
@@ -426,14 +460,15 @@ static int dsp_task_config(struct dsptask *task, unsigned char tid)
ipbcfg
.
lsz
*
2
;
/* passive block */
return
0
;
fail_out:
dsptask
[
tid
]
=
NULL
;
return
ret
;
}
static
void
dsp_task_init
(
struct
dsptask
*
task
)
{
struct
mbcmd
mb
;
mbcmd_set
(
mb
,
MBCMD
(
TCTL
),
task
->
tid
,
OMAP_DSP_MBCMD_TCTL_TINIT
);
dsp_mbsend
(
&
mb
);
dsp_mbsend
(
MBCMD
(
TCTL
),
task
->
tid
,
OMAP_DSP_MBCMD_TCTL_TINIT
);
}
int
dsp_task_config_all
(
unsigned
char
n
)
...
...
@@ -558,11 +593,22 @@ int dsp_taskmod_busy(void)
for
(
minor
=
0
;
minor
<
TASKDEV_MAX
;
minor
++
)
{
dev
=
taskdev
[
minor
];
if
(
dev
&&
((
dev
->
usecount
>
0
)
||
(
dev
->
state
==
OMAP_DSP_DEVSTATE_ADDREQ
)
||
(
dev
->
state
==
OMAP_DSP_DEVSTATE_DELREQ
)))
if
(
dev
==
NULL
)
continue
;
if
(
dev
->
usecount
>
0
)
{
printk
(
"dsp_taskmod_busy(): %s: usecount=%d
\n
"
,
dev
->
name
,
dev
->
usecount
);
return
1
;
}
/*
if ((dev->state & (OMAP_DSP_DEVSTATE_ADDREQ |
OMAP_DSP_DEVSTATE_DELREQ)) {
*/
if
(
dev
->
state
&
OMAP_DSP_DEVSTATE_ADDREQ
)
{
printk
(
"dsp_taskmod_busy(): %s is in %s
\n
"
,
dev
->
name
,
devstate_name
(
dev
->
state
));
return
1
;
}
}
return
0
;
}
...
...
@@ -704,13 +750,19 @@ static ssize_t dsp_task_read_bk_acv(struct file *file, char *buf, size_t count,
ret
=
-
ERESTARTSYS
;
goto
up_out
;
}
base
=
dspword_to_virt
(
MKLONG
(
ipbp
->
ah
,
ipbp
->
al
));
src
=
base
+
rcvdt
->
rp
;
base
=
MKVIRT
(
ipbp
->
ah
,
ipbp
->
al
);
bkcnt
=
((
unsigned
long
)
ipbp
->
c
)
*
2
-
rcvdt
->
rp
;
if
(
dsp_address_validate
(
base
,
bkcnt
,
"task %s read buffer"
,
dev
->
task
->
name
)
<
0
)
{
ret
=
-
ERESTARTSYS
;
goto
pv_out1
;
}
if
(
dsp_mem_enable
(
base
)
<
0
)
{
ret
=
-
ERESTARTSYS
;
goto
pv_out1
;
}
bkcnt
=
((
unsigned
long
)
ipbp
->
c
)
*
2
-
rcvdt
->
rp
;
src
=
base
+
rcvdt
->
rp
;
if
(
bkcnt
>
count
)
{
if
(
copy_to_user_dsp
(
buf
,
src
,
count
))
{
ret
=
-
EFAULT
;
...
...
@@ -813,7 +865,7 @@ static ssize_t dsp_task_read_wd_psv(struct file *file, char *buf, size_t count,
devstate_unlock
(
dev
);
mbcmd_set
(
mb
,
MBCMD
(
WDREQ
),
tid
,
0
);
dsp_mbsend_and_wait
(
&
mb
,
&
dev
->
read_wait_q
);
dsp_mb
cmd_
send_and_wait
(
&
mb
,
&
dev
->
read_wait_q
);
if
(
signal_pending
(
current
))
{
ret
=
-
ERESTARTSYS
;
...
...
@@ -868,7 +920,7 @@ static ssize_t dsp_task_read_bk_psv(struct file *file, char *buf, size_t count,
devstate_unlock
(
dev
);
mbcmd_set
(
mb
,
MBCMD
(
BKREQ
),
tid
,
count
/
2
);
dsp_mbsend_and_wait
(
&
mb
,
&
dev
->
read_wait_q
);
dsp_mb
cmd_
send_and_wait
(
&
mb
,
&
dev
->
read_wait_q
);
if
(
signal_pending
(
current
))
{
ret
=
-
ERESTARTSYS
;
...
...
@@ -896,12 +948,17 @@ static ssize_t dsp_task_read_bk_psv(struct file *file, char *buf, size_t count,
ret
=
-
ERESTARTSYS
;
goto
unlock_out
;
}
src
=
dspword_to_virt
(
MKLONG
(
ipbp
->
ah
,
ipbp
->
al
));
src
=
MKVIRT
(
ipbp
->
ah
,
ipbp
->
al
);
rcvcnt
=
((
unsigned
long
)
ipbp
->
c
)
*
2
;
if
(
dsp_address_validate
(
src
,
rcvcnt
,
"task %s read buffer"
,
dev
->
task
->
name
)
<
0
)
{
ret
=
-
ERESTARTSYS
;
goto
pv_out1
;
}
if
(
dsp_mem_enable
(
src
)
<
0
)
{
ret
=
-
ERESTARTSYS
;
goto
pv_out1
;
}
rcvcnt
=
((
unsigned
long
)
ipbp
->
c
)
*
2
;
if
(
count
>
rcvcnt
)
count
=
rcvcnt
;
if
(
copy_to_user_dsp
(
buf
,
src
,
count
))
{
...
...
@@ -955,7 +1012,6 @@ static ssize_t dsp_task_write_wd(struct file *file, const char *buf,
{
unsigned
int
minor
=
MINOR
(
file
->
f_dentry
->
d_inode
->
i_rdev
);
struct
taskdev
*
dev
=
taskdev
[
minor
];
struct
mbcmd
mb
;
unsigned
short
wd
;
int
have_devstate_lock
=
0
;
int
ret
=
0
;
...
...
@@ -1013,9 +1069,8 @@ static ssize_t dsp_task_write_wd(struct file *file, const char *buf,
goto
up_out
;
}
mbcmd_set
(
mb
,
MBCMD
(
WDSND
),
dev
->
task
->
tid
,
wd
);
spin_lock
(
&
dev
->
task
->
wsz_lock
);
if
(
dsp_mbsend
(
&
mb
)
<
0
)
{
if
(
dsp_mbsend
(
MBCMD
(
WDSND
),
dev
->
task
->
tid
,
wd
)
<
0
)
{
spin_unlock
(
&
dev
->
task
->
wsz_lock
);
goto
up_out
;
}
...
...
@@ -1036,7 +1091,6 @@ static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
{
unsigned
int
minor
=
MINOR
(
file
->
f_dentry
->
d_inode
->
i_rdev
);
struct
taskdev
*
dev
=
taskdev
[
minor
];
struct
mbcmd
mb
;
int
have_devstate_lock
=
0
;
int
ret
=
0
;
...
...
@@ -1102,7 +1156,12 @@ static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
ret
=
-
ERESTARTSYS
;
goto
up_out
;
}
dst
=
dspword_to_virt
(
MKLONG
(
ipbp
->
ah
,
ipbp
->
al
));
dst
=
MKVIRT
(
ipbp
->
ah
,
ipbp
->
al
);
if
(
dsp_address_validate
(
dst
,
count
,
"task %s write buffer"
,
dev
->
task
->
name
)
<
0
)
{
ret
=
-
ERESTARTSYS
;
goto
pv_out1
;
}
if
(
dsp_mem_enable
(
dst
)
<
0
)
{
ret
=
-
ERESTARTSYS
;
goto
pv_out1
;
...
...
@@ -1113,9 +1172,8 @@ static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
}
ipbp
->
c
=
count
/
2
;
ipbp
->
s
=
dev
->
task
->
tid
;
mbcmd_set
(
mb
,
MBCMD
(
BKSNDP
),
dev
->
task
->
tid
,
0
);
spin_lock
(
&
dev
->
task
->
wsz_lock
);
if
(
dsp_mbsend
(
&
mb
)
==
0
)
{
if
(
dsp_mbsend
(
MBCMD
(
BKSNDP
),
dev
->
task
->
tid
,
0
)
==
0
)
{
if
(
rcvtyp_acv
(
dev
->
task
->
ttyp
))
dev
->
task
->
wsz
=
0
;
ret
=
count
;
...
...
@@ -1145,9 +1203,8 @@ pv_out1:
}
ipbp
->
c
=
count
/
2
;
ipbp
->
sa
=
dev
->
task
->
tid
;
mbcmd_set
(
mb
,
MBCMD
(
BKSND
),
dev
->
task
->
tid
,
bid
);
spin_lock
(
&
dev
->
task
->
wsz_lock
);
if
(
dsp_mbsend
(
&
mb
)
==
0
)
{
if
(
dsp_mbsend
(
MBCMD
(
BKSND
),
dev
->
task
->
tid
,
bid
)
==
0
)
{
if
(
rcvtyp_acv
(
dev
->
task
->
ttyp
))
dev
->
task
->
wsz
=
0
;
ret
=
count
;
...
...
@@ -1226,6 +1283,9 @@ static int dsp_task_ioctl(struct inode *inode, struct file *file,
* reserved for backward compatibility
* user-defined TCTL commands: no arg, non-interactive
*/
printk
(
KERN_WARNING
"omapdsp: "
"TCTL commands in 0x0080 - 0x0100 are obsolete.
\n
"
"they won't be supported in the future.
\n
"
);
mbargc
=
0
;
interactive
=
0
;
}
else
if
(
cmd
<
0x8000
)
{
...
...
@@ -1315,7 +1375,7 @@ static int dsp_task_ioctl(struct inode *inode, struct file *file,
dev
->
task
->
tctl_stat
=
-
ERESTARTSYS
;
devstate_unlock
(
dev
);
dsp_mbsend_and_wait_exarg
(
&
mb
,
mbargp
,
&
dev
->
ioctl_wait_q
);
dsp_mb
cmd_
send_and_wait_exarg
(
&
mb
,
mbargp
,
&
dev
->
ioctl_wait_q
);
if
(
signal_pending
(
current
))
{
ret
=
-
ERESTARTSYS
;
goto
up_out
;
...
...
@@ -1330,7 +1390,7 @@ static int dsp_task_ioctl(struct inode *inode, struct file *file,
goto
unlock_out
;
}
}
else
{
dsp_mbsend_exarg
(
&
mb
,
mbargp
);
dsp_mb
cmd_
send_exarg
(
&
mb
,
mbargp
);
ret
=
0
;
}
...
...
@@ -1341,18 +1401,42 @@ up_out:
return
ret
;
}
static
void
dsp_task_mmap_open
(
struct
vm_area_struct
*
vma
)
{
struct
taskdev
*
dev
=
(
struct
taskdev
*
)
vma
->
vm_private_data
;
struct
dsptask
*
task
;
size_t
len
=
vma
->
vm_end
-
vma
->
vm_start
;
BUG_ON
(
!
(
dev
->
state
&
OMAP_DSP_DEVSTATE_ATTACHED
));
task
=
dev
->
task
;
exmap_use
(
task
->
map_base
,
len
);
}
static
void
dsp_task_mmap_close
(
struct
vm_area_struct
*
vma
)
{
struct
taskdev
*
dev
=
(
struct
taskdev
*
)
vma
->
vm_private_data
;
struct
dsptask
*
task
;
size_t
len
=
vma
->
vm_end
-
vma
->
vm_start
;
BUG_ON
(
!
(
dev
->
state
&
OMAP_DSP_DEVSTATE_ATTACHED
));
task
=
dev
->
task
;
exmap_unuse
(
task
->
map_base
,
len
);
}
/**
* On demand page allocation is not allowed. The mapping area is defined by
* corresponding DSP tasks.
*/
static
struct
page
*
dsp_task_
nopage_mmap
(
struct
vm_area_struct
*
vma
,
static
struct
page
*
dsp_task_
mmap_nopage
(
struct
vm_area_struct
*
vma
,
unsigned
long
address
,
int
*
type
)
{
return
NOPAGE_SIGBUS
;
}
static
struct
vm_operations_struct
dsp_task_vm_ops
=
{
.
nopage
=
dsp_task_nopage_mmap
,
.
open
=
dsp_task_mmap_open
,
.
close
=
dsp_task_mmap_close
,
.
nopage
=
dsp_task_mmap_nopage
,
};
static
int
dsp_task_mmap
(
struct
file
*
filp
,
struct
vm_area_struct
*
vma
)
...
...
@@ -1368,21 +1452,6 @@ static int dsp_task_mmap(struct file *filp, struct vm_area_struct *vma)
if
(
devstate_lock
(
dev
,
OMAP_DSP_DEVSTATE_ATTACHED
)
<
0
)
return
-
ERESTARTSYS
;
task
=
dev
->
task
;
if
(
task
->
map_length
==
0
)
{
printk
(
KERN_ERR
"omapdsp: task %s doesn't have mmap buffer.
\n
"
,
task
->
name
);
ret
=
-
EINVAL
;
goto
unlock_out
;
}
if
(
is_dsp_internal_mem
(
task
->
map_base
))
{
printk
(
KERN_ERR
"omapdsp: task %s: map_base = %p
\n
"
" DARAM/SARAM can't be used as mmap buffer.
\n
"
,
task
->
name
,
task
->
map_base
);
ret
=
-
EINVAL
;
goto
unlock_out
;
}
/*
* Don't swap this area out
...
...
@@ -1430,6 +1499,9 @@ static int dsp_task_mmap(struct file *filp, struct vm_area_struct *vma)
}
while
(
req_len
);
vma
->
vm_ops
=
&
dsp_task_vm_ops
;
vma
->
vm_private_data
=
dev
;
exmap_use
(
task
->
map_base
,
vma
->
vm_end
-
vma
->
vm_start
);
unlock_out:
devstate_unlock
(
dev
);
return
ret
;
...
...
@@ -1441,12 +1513,8 @@ static int dsp_task_open(struct inode *inode, struct file *file)
struct
taskdev
*
dev
;
int
ret
=
0
;
if
(
minor
>=
TASKDEV_MAX
)
return
-
ENODEV
;
dev
=
taskdev
[
minor
];
if
(
dev
==
NULL
)
if
((
minor
>=
TASKDEV_MAX
)
||
((
dev
=
taskdev
[
minor
])
==
NULL
))
return
-
ENODEV
;
if
(
devstate_lock
(
dev
,
OMAP_DSP_DEVSTATE_NOTASK
|
OMAP_DSP_DEVSTATE_ATTACHED
)
<
0
)
return
-
ERESTARTSYS
;
...
...
@@ -1457,15 +1525,20 @@ static int dsp_task_open(struct inode *inode, struct file *file)
}
#endif
if
(
dev
->
state
==
OMAP_DSP_DEVSTATE_NOTASK
)
{
if
(
dev
->
state
&
OMAP_DSP_DEVSTATE_NOTASK
)
{
dev
->
state
=
OMAP_DSP_DEVSTATE_ADDREQ
;
/* wake up twch daemon for tadd */
dsp_twch_touch
();
devstate_unlock
(
dev
);
if
(
devstate_lock
(
dev
,
OMAP_DSP_DEVSTATE_ATTACHED
|
OMAP_DSP_DEVSTATE_ADDFAIL
)
<
0
)
OMAP_DSP_DEVSTATE_ADDFAIL
)
<
0
)
{
spin_lock
(
&
dev
->
state_lock
);
if
(
dev
->
state
&
OMAP_DSP_DEVSTATE_ADDREQ
)
dev
->
state
=
OMAP_DSP_DEVSTATE_NOTASK
;
spin_unlock
(
&
dev
->
state_lock
);
return
-
ERESTARTSYS
;
if
(
dev
->
state
==
OMAP_DSP_DEVSTATE_ADDFAIL
)
{
}
if
(
dev
->
state
&
OMAP_DSP_DEVSTATE_ADDFAIL
)
{
printk
(
KERN_ERR
"omapdsp: task attach failed for %s!
\n
"
,
dev
->
name
);
ret
=
-
EBUSY
;
...
...
@@ -1496,10 +1569,10 @@ static int dsp_task_release(struct inode *inode, struct file *file)
/* state_lock covers usecount, proc_list as well. */
spin_lock
(
&
dev
->
state_lock
);
/* state can be ATTACHED, KILL
REQ
or GARBAGE here. */
switch
(
dev
->
state
)
{
/* state can be ATTACHED, KILL
ING
or GARBAGE here. */
switch
(
dev
->
state
&
OMAP_DSP_DEVSTATE_STATE_MASK
)
{
case
OMAP_DSP_DEVSTATE_KILL
REQ
:
case
OMAP_DSP_DEVSTATE_KILL
ING
:
dev
->
usecount
--
;
break
;
...
...
@@ -1582,11 +1655,10 @@ int dsp_rmdev(char *name)
static
int
dsp_rmdev_minor
(
unsigned
char
minor
)
{
struct
taskdev
*
dev
=
taskdev
[
minor
];
struct
dsptask
*
task
=
dev
->
task
;
spin_lock
(
&
dev
->
state_lock
);
switch
(
dev
->
state
)
{
switch
(
dev
->
state
&
OMAP_DSP_DEVSTATE_STATE_MASK
)
{
case
OMAP_DSP_DEVSTATE_NOTASK
:
/* fine */
...
...
@@ -1598,6 +1670,7 @@ static int dsp_rmdev_minor(unsigned char minor)
siginfo_t
info
;
struct
proc_list
*
pl
;
dev
->
state
=
OMAP_DSP_DEVSTATE_KILLING
;
info
.
si_signo
=
SIGBUS
;
info
.
si_errno
=
0
;
info
.
si_code
=
SI_KERNEL
;
...
...
@@ -1605,12 +1678,10 @@ static int dsp_rmdev_minor(unsigned char minor)
list_for_each_entry
(
pl
,
&
dev
->
proc_list
,
list_head
)
{
send_sig_info
(
SIGBUS
,
&
info
,
pl
->
tsk
);
}
taskdev_detach_task
(
dev
);
dsp_task_unconfig
(
task
);
kfree
(
task
);
dev
->
state
=
OMAP_DSP_DEVSTATE_GARBAGE
;
spin_unlock
(
&
dev
->
state_lock
);
dsp_tdel_bh
(
minor
,
OMAP_DSP_MBCMD_TDEL_KILL
);
goto
invalidate
;
}
break
;
case
OMAP_DSP_DEVSTATE_ADDREQ
:
/* open() is waiting. drain it. */
...
...
@@ -1624,7 +1695,9 @@ static int dsp_rmdev_minor(unsigned char minor)
wake_up_interruptible_all
(
&
dev
->
state_wait_q
);
break
;
case
OMAP_DSP_DEVSTATE_KILLREQ
:
case
OMAP_DSP_DEVSTATE_ADDING
:
case
OMAP_DSP_DEVSTATE_DELING
:
case
OMAP_DSP_DEVSTATE_KILLING
:
case
OMAP_DSP_DEVSTATE_GARBAGE
:
case
OMAP_DSP_DEVSTATE_ADDFAIL
:
/* transient state. wait for a moment. */
...
...
@@ -1634,12 +1707,13 @@ static int dsp_rmdev_minor(unsigned char minor)
spin_unlock
(
&
dev
->
state_lock
);
invalidate:
/* wait for some time and hope the state is settled */
devstate_lock_timeout
(
dev
,
OMAP_DSP_DEVSTATE_NOTASK
,
HZ
);
if
(
dev
->
state
!=
OMAP_DSP_DEVSTATE_NOTASK
)
{
if
(
!
(
dev
->
state
&
OMAP_DSP_DEVSTATE_NOTASK
)
)
{
printk
(
KERN_WARNING
"omapdsp: illegal device state on rmdev %s.
\n
"
,
dev
->
name
);
"omapdsp: illegal device state
(%s)
on rmdev %s.
\n
"
,
dev
state_name
(
dev
->
state
),
dev
->
name
);
}
dev
->
state
=
OMAP_DSP_DEVSTATE_INVALID
;
devstate_unlock
(
dev
);
...
...
@@ -1656,7 +1730,6 @@ struct file_operations dsp_task_fops = {
.
ioctl
=
dsp_task_ioctl
,
.
open
=
dsp_task_open
,
.
release
=
dsp_task_release
,
.
mmap
=
dsp_task_mmap
,
};
static
void
dsptask_dev_release
(
struct
device
*
dev
)
...
...
@@ -1694,8 +1767,6 @@ static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor)
device_create_file
(
&
dev
->
dev
,
&
dev_attr_proc_list
);
class_device_create
(
dsp_task_class
,
MKDEV
(
OMAP_DSP_TASK_MAJOR
,
minor
),
NULL
,
"dsptask%d"
,
minor
);
devfs_mk_cdev
(
MKDEV
(
OMAP_DSP_TASK_MAJOR
,
minor
),
S_IFCHR
|
S_IRUGO
|
S_IWUGO
,
"dsptask%d"
,
minor
);
init_waitqueue_head
(
&
dev
->
state_wait_q
);
spin_lock_init
(
&
dev
->
state_lock
);
...
...
@@ -1712,9 +1783,7 @@ static void taskdev_delete(unsigned char minor)
device_remove_file
(
&
dev
->
dev
,
&
dev_attr_devname
);
device_remove_file
(
&
dev
->
dev
,
&
dev_attr_devstate
);
device_remove_file
(
&
dev
->
dev
,
&
dev_attr_proc_list
);
class_device_destroy
(
dsp_task_class
,
MKDEV
(
OMAP_DSP_TASK_MAJOR
,
minor
));
devfs_remove
(
"dsptask%d"
,
minor
);
device_unregister
(
&
dev
->
dev
);
proc_list_flush
(
&
dev
->
proc_list
);
taskdev
[
minor
]
=
NULL
;
...
...
@@ -1736,6 +1805,8 @@ static void taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
dev
->
fops
.
write
=
rcvtyp_wd
(
ttyp
)
?
dsp_task_write_wd
:
/* rcvbyp_bk */
dsp_task_write_bk
;
if
(
task
->
map_length
)
dev
->
fops
.
mmap
=
dsp_task_mmap
;
device_create_file
(
&
dev
->
dev
,
&
dev_attr_taskname
);
device_create_file
(
&
dev
->
dev
,
&
dev_attr_ttyp
);
...
...
@@ -1781,7 +1852,7 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
struct
dsptask
*
task
;
struct
mbcmd
mb
;
struct
mb_exarg
arg
;
unsigned
char
tid
;
unsigned
char
tid
,
tid_response
;
unsigned
short
argv
[
2
];
int
ret
=
minor
;
...
...
@@ -1790,16 +1861,17 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
"omapdsp: no task device with minor %d
\n
"
,
minor
);
return
-
EINVAL
;
}
/*
* we don't need to lock state_lock because
* only tadd is allowed when devstate is ADDREQ.
*/
if
(
dev
->
state
!=
OMAP_DSP_DEVSTATE_ADDREQ
)
{
spin_lock
(
&
dev
->
state_lock
);
if
(
!
(
dev
->
state
&
OMAP_DSP_DEVSTATE_ADDREQ
))
{
printk
(
KERN_ERR
"omapdsp: taskdev %s is not requesting for tadd.
\n
"
,
dev
->
name
);
"omapdsp: taskdev %s is not requesting for tadd. "
"(state is %s)
\n
"
,
dev
->
name
,
devstate_name
(
dev
->
state
));
spin_unlock
(
&
dev
->
state_lock
);
return
-
EINVAL
;
}
dev
->
state
=
OMAP_DSP_DEVSTATE_ADDING
;
spin_unlock
(
&
dev
->
state_lock
);
if
(
adr
==
OMAP_DSP_TADD_ABORTADR
)
{
/* aborting tadd intentionally */
...
...
@@ -1828,7 +1900,8 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
arg
.
argc
=
2
;
arg
.
argv
=
argv
;
dsp_mbsend_and_wait_exarg
(
&
mb
,
&
arg
,
&
cfg_wait_q
);
dsp_mem_sync_inc
();
dsp_mbcmd_send_and_wait_exarg
(
&
mb
,
&
arg
,
&
cfg_wait_q
);
tid
=
cfg_tid
;
cfg_tid
=
OMAP_DSP_TID_ANON
;
...
...
@@ -1847,7 +1920,7 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
}
if
((
task
=
kmalloc
(
sizeof
(
struct
dsptask
),
GFP_KERNEL
))
==
NULL
)
{
ret
=
-
ENOMEM
;
goto
fai
l_out
;
goto
de
l_out
;
}
memset
(
task
,
0
,
sizeof
(
struct
dsptask
));
...
...
@@ -1860,9 +1933,7 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
"omapdsp: task name (%s) doesn't match with "
"device name (%s).
\n
"
,
task
->
name
,
dev
->
name
);
ret
=
-
EINVAL
;
dev
->
state
=
OMAP_DSP_DEVSTATE_DELREQ
;
dsp_twch_touch
();
return
-
EINVAL
;
goto
free_out
;
}
dsp_task_init
(
task
);
...
...
@@ -1873,6 +1944,30 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
free_out:
kfree
(
task
);
del_out:
printk
(
KERN_ERR
"omapdsp: deleting the task...
\n
"
);
dev
->
state
=
OMAP_DSP_DEVSTATE_DELING
;
if
(
down_interruptible
(
&
cfg_sem
))
{
printk
(
KERN_ERR
"omapdsp: aborting tdel process. "
"DSP side could be corrupted.
\n
"
);
goto
fail_out
;
}
cfg_tid
=
OMAP_DSP_TID_ANON
;
cfg_cmd
=
MBCMD
(
TDEL
);
mbcmd_set
(
mb
,
MBCMD
(
TDEL
),
tid
,
OMAP_DSP_MBCMD_TDEL_KILL
);
dsp_mbcmd_send_and_wait
(
&
mb
,
&
cfg_wait_q
);
tid_response
=
cfg_tid
;
cfg_tid
=
OMAP_DSP_TID_ANON
;
cfg_cmd
=
0
;
up
(
&
cfg_sem
);
if
(
tid_response
!=
tid
)
printk
(
KERN_ERR
"omapdsp: tdel failed. "
"DSP side could be corrupted.
\n
"
);
fail_out:
dev
->
state
=
OMAP_DSP_DEVSTATE_ADDFAIL
;
wake_up_interruptible_all
(
&
dev
->
state_wait_q
);
...
...
@@ -1882,64 +1977,31 @@ fail_out:
int
dsp_tdel
(
unsigned
char
minor
)
{
struct
taskdev
*
dev
;
struct
dsptask
*
task
;
struct
mbcmd
mb
;
unsigned
char
tid
,
tid_response
;
int
ret
=
minor
;
if
((
minor
>=
TASKDEV_MAX
)
||
((
dev
=
taskdev
[
minor
])
==
NULL
))
{
printk
(
KERN_ERR
"omapdsp: no task device with minor %d
\n
"
,
minor
);
return
-
EINVAL
;
}
/*
* we don't need to lock state_lock because
* only tdel is allowed when devstate is DELREQ.
*/
if
(
dev
->
state
!=
OMAP_DSP_DEVSTATE_DELREQ
)
{
spin_lock
(
&
dev
->
state_lock
);
if
(
!
(
dev
->
state
&
OMAP_DSP_DEVSTATE_DELREQ
))
{
printk
(
KERN_ERR
"omapdsp: taskdev %s is not requesting for tdel.
\n
"
,
dev
->
name
);
"omapdsp: taskdev %s is not requesting for tdel. "
"(state is %s)
\n
"
,
dev
->
name
,
devstate_name
(
dev
->
state
));
spin_unlock
(
&
dev
->
state_lock
);
return
-
EINVAL
;
}
dev
->
state
=
OMAP_DSP_DEVSTATE_DELING
;
spin_unlock
(
&
dev
->
state_lock
);
task
=
dev
->
task
;
tid
=
task
->
tid
;
if
(
down_interruptible
(
&
cfg_sem
))
{
return
-
ERESTARTSYS
;
}
cfg_tid
=
OMAP_DSP_TID_ANON
;
cfg_cmd
=
MBCMD
(
TDEL
);
mbcmd_set
(
mb
,
MBCMD
(
TDEL
),
tid
,
OMAP_DSP_MBCMD_TDEL_SAFE
);
dsp_mbsend_and_wait
(
&
mb
,
&
cfg_wait_q
);
tid_response
=
cfg_tid
;
cfg_tid
=
OMAP_DSP_TID_ANON
;
cfg_cmd
=
0
;
up
(
&
cfg_sem
);
taskdev_detach_task
(
dev
);
dsp_task_unconfig
(
task
);
kfree
(
task
);
dev
->
state
=
OMAP_DSP_DEVSTATE_NOTASK
;
wake_up_interruptible_all
(
&
dev
->
state_wait_q
);
if
(
tid_response
!=
tid
)
{
printk
(
KERN_ERR
"omapdsp: tdel failed!
\n
"
);
ret
=
-
EINVAL
;
}
return
ret
;
return
dsp_tdel_bh
(
minor
,
OMAP_DSP_MBCMD_TDEL_SAFE
);
}
int
dsp_tkill
(
unsigned
char
minor
)
{
struct
taskdev
*
dev
;
struct
dsptask
*
task
;
struct
mbcmd
mb
;
unsigned
char
tid
,
tid_response
;
siginfo_t
info
;
struct
proc_list
*
pl
;
int
ret
=
minor
;
if
((
minor
>=
TASKDEV_MAX
)
||
((
dev
=
taskdev
[
minor
])
==
NULL
))
{
printk
(
KERN_ERR
...
...
@@ -1947,14 +2009,14 @@ int dsp_tkill(unsigned char minor)
return
-
EINVAL
;
}
spin_lock
(
&
dev
->
state_lock
);
if
(
dev
->
state
!=
OMAP_DSP_DEVSTATE_ATTACHED
)
{
if
(
!
(
dev
->
state
&
OMAP_DSP_DEVSTATE_ATTACHED
)
)
{
printk
(
KERN_ERR
"omapdsp: task has not been attached for taskdev %s
\n
"
,
dev
->
name
);
spin_unlock
(
&
dev
->
state_lock
);
return
-
EINVAL
;
}
dev
->
state
=
OMAP_DSP_DEVSTATE_KILL
REQ
;
dev
->
state
=
OMAP_DSP_DEVSTATE_KILL
ING
;
info
.
si_signo
=
SIGBUS
;
info
.
si_errno
=
0
;
info
.
si_code
=
SI_KERNEL
;
...
...
@@ -1964,17 +2026,33 @@ int dsp_tkill(unsigned char minor)
}
spin_unlock
(
&
dev
->
state_lock
);
return
dsp_tdel_bh
(
minor
,
OMAP_DSP_MBCMD_TDEL_KILL
);
}
static
int
dsp_tdel_bh
(
unsigned
char
minor
,
unsigned
short
type
)
{
struct
taskdev
*
dev
=
taskdev
[
minor
];
struct
dsptask
*
task
;
struct
mbcmd
mb
;
unsigned
char
tid
,
tid_response
;
int
ret
=
minor
;
task
=
dev
->
task
;
tid
=
task
->
tid
;
if
(
down_interruptible
(
&
cfg_sem
))
{
tid_response
=
OMAP_DSP_TID_ANON
;
ret
=
-
ERESTARTSYS
;
goto
detach_out
;
if
(
type
==
OMAP_DSP_MBCMD_TDEL_SAFE
)
{
dev
->
state
=
OMAP_DSP_DEVSTATE_DELREQ
;
return
-
ERESTARTSYS
;
}
else
{
tid_response
=
OMAP_DSP_TID_ANON
;
ret
=
-
ERESTARTSYS
;
goto
detach_out
;
}
}
cfg_tid
=
OMAP_DSP_TID_ANON
;
cfg_cmd
=
MBCMD
(
TDEL
);
mbcmd_set
(
mb
,
MBCMD
(
TDEL
),
tid
,
OMAP_DSP_MBCMD_TDEL_KILL
);
dsp_mbsend_and_wait
(
&
mb
,
&
cfg_wait_q
);
mbcmd_set
(
mb
,
MBCMD
(
TDEL
),
tid
,
type
);
dsp_mb
cmd_
send_and_wait
(
&
mb
,
&
cfg_wait_q
);
tid_response
=
cfg_tid
;
cfg_tid
=
OMAP_DSP_TID_ANON
;
cfg_cmd
=
0
;
...
...
@@ -1985,9 +2063,11 @@ detach_out:
dsp_task_unconfig
(
task
);
kfree
(
task
);
if
(
tid_response
!=
tid
)
printk
(
KERN_ERR
"omapdsp: tkill failed!
\n
"
);
if
(
tid_response
!=
tid
)
{
printk
(
KERN_ERR
"omapdsp: %s failed!
\n
"
,
(
type
==
OMAP_DSP_MBCMD_TDEL_SAFE
)
?
"tdel"
:
"tkill"
);
ret
=
-
EINVAL
;
}
spin_lock
(
&
dev
->
state_lock
);
dev
->
state
=
(
dev
->
usecount
>
0
)
?
OMAP_DSP_DEVSTATE_GARBAGE
:
OMAP_DSP_DEVSTATE_NOTASK
;
...
...
@@ -2000,10 +2080,14 @@ detach_out:
/*
* state inquiry
*/
long
taskdev_state
(
unsigned
char
minor
)
long
taskdev_state
_stale
(
unsigned
char
minor
)
{
return
taskdev
[
minor
]
?
taskdev
[
minor
]
->
state
:
OMAP_DSP_DEVSTATE_NOTASK
;
if
(
taskdev
[
minor
])
{
long
state
=
taskdev
[
minor
]
->
state
;
taskdev
[
minor
]
->
state
|=
OMAP_DSP_DEVSTATE_STALE
;
return
state
;
}
else
return
OMAP_DSP_DEVSTATE_NOTASK
;
}
/*
...
...
@@ -2271,9 +2355,6 @@ void mbx1_tcfg(struct mbcmd *mb)
{
unsigned
char
tid
=
mb
->
cmd_l
;
struct
dsptask
*
task
=
dsptask
[
tid
];
unsigned
long
tmp_ipbp_r
,
tmp_ipbp_w
;
unsigned
long
tmp_mapstart
,
tmp_maplen
;
unsigned
long
tmp_tnm
;
unsigned
short
*
tnm
;
volatile
unsigned
short
*
buf
;
int
i
;
...
...
@@ -2289,25 +2370,29 @@ void mbx1_tcfg(struct mbcmd *mb)
if
(
sync_with_dsp
(
&
ipbuf_sys_da
->
s
,
tid
,
10
)
<
0
)
{
printk
(
KERN_ERR
"mbx: TCFG - IPBUF sync failed!
\n
"
);
return
;
goto
out
;
}
/*
* read configuration data on system IPBUF
*/
buf
=
ipbuf_sys_da
->
d
;
task
->
ttyp
=
buf
[
0
];
tmp_ipbp_r
=
MKLONG
(
buf
[
1
],
buf
[
2
]);
tmp_ipbp_w
=
MKLONG
(
buf
[
3
],
buf
[
4
]);
tmp_mapstart
=
MKLONG
(
buf
[
5
],
buf
[
6
]);
tmp_maplen
=
MKLONG
(
buf
[
7
],
buf
[
8
]);
tmp_tnm
=
MKLONG
(
buf
[
9
],
buf
[
10
]);
task
->
rcvdt
.
bk
.
ipbuf_pvt_r
=
dspword_to_virt
(
tmp_ipbp_r
);
task
->
ipbuf_pvt_w
=
dspword_to_virt
(
tmp_ipbp_w
);
task
->
map_base
=
dspword_to_virt
(
tmp_mapstart
);
task
->
map_length
=
tmp_maplen
<<
1
;
/* word -> byte */
tnm
=
dspword_to_virt
(
tmp_tnm
);
task
->
ttyp
=
buf
[
0
];
task
->
rcvdt
.
bk
.
ipbuf_pvt_r
=
MKVIRT
(
buf
[
1
],
buf
[
2
]);
task
->
ipbuf_pvt_w
=
MKVIRT
(
buf
[
3
],
buf
[
4
]);
task
->
map_base
=
MKVIRT
(
buf
[
5
],
buf
[
6
]);
task
->
map_length
=
MKLONG
(
buf
[
7
],
buf
[
8
])
<<
1
;
/* word -> byte */
tnm
=
MKVIRT
(
buf
[
9
],
buf
[
10
]);
release_ipbuf_pvt
(
ipbuf_sys_da
);
/*
* copy task name string
*/
if
(
dsp_address_validate
(
tnm
,
OMAP_DSP_TNM_LEN
,
"task name buffer"
)
<
0
)
{
task
->
name
[
0
]
=
'\0'
;
goto
out
;
}
for
(
i
=
0
;
i
<
OMAP_DSP_TNM_LEN
-
1
;
i
++
)
{
/* avoiding byte access */
unsigned
short
tmp
=
tnm
[
i
];
...
...
@@ -2317,8 +2402,8 @@ void mbx1_tcfg(struct mbcmd *mb)
}
task
->
name
[
OMAP_DSP_TNM_LEN
-
1
]
=
'\0'
;
release_ipbuf_pvt
(
ipbuf_sys_da
);
task
->
state
=
TASK_STATE_READY
;
out:
wake_up_interruptible
(
&
cfg_wait_q
);
}
...
...
@@ -2368,7 +2453,117 @@ void mbx1_err_fatal(unsigned char tid)
spin_unlock
(
&
task
->
dev
->
state_lock
);
}
static
short
*
dbg_buf
;
static
unsigned
short
dbg_buf_sz
,
dbg_line_sz
;
static
int
dbg_rp
;
int
dsp_dbg_config
(
short
*
buf
,
unsigned
short
sz
,
unsigned
short
lsz
)
{
#ifdef OLD_BINARY_SUPPORT
if
((
mbx_revision
==
MBREV_3_0
)
||
(
mbx_revision
==
MBREV_3_2
))
{
dbg_buf
=
NULL
;
dbg_buf_sz
=
0
;
dbg_line_sz
=
0
;
dbg_rp
=
0
;
return
0
;
}
#endif
if
(
dsp_address_validate
(
buf
,
sz
,
"debug buffer"
)
<
0
)
return
-
1
;
if
(
lsz
>
sz
)
{
printk
(
KERN_ERR
"omapdsp: dbg_buf lsz (%d) is greater than its "
"buffer size (%d)
\n
"
,
lsz
,
sz
);
return
-
1
;
}
dbg_buf
=
buf
;
dbg_buf_sz
=
sz
;
dbg_line_sz
=
lsz
;
dbg_rp
=
0
;
return
0
;
}
void
dsp_dbg_stop
(
void
)
{
dbg_buf
=
NULL
;
}
#ifdef OLD_BINARY_SUPPORT
static
void
mbx1_dbg_old
(
struct
mbcmd
*
mb
);
#endif
void
mbx1_dbg
(
struct
mbcmd
*
mb
)
{
unsigned
char
tid
=
mb
->
cmd_l
;
int
cnt
=
mb
->
data
;
char
s
[
80
],
*
s_end
=
&
s
[
79
],
*
p
;
unsigned
short
*
src
;
int
i
;
#ifdef OLD_BINARY_SUPPORT
if
((
mbx_revision
==
MBREV_3_0
)
||
(
mbx_revision
==
MBREV_3_2
))
{
mbx1_dbg_old
(
mb
);
return
;
}
#endif
if
(((
tid
>=
TASKDEV_MAX
)
||
(
dsptask
[
tid
]
==
NULL
))
&&
(
tid
!=
OMAP_DSP_TID_ANON
))
{
printk
(
KERN_ERR
"mbx: DBG with illegal tid! %d
\n
"
,
tid
);
return
;
}
if
(
dbg_buf
==
NULL
)
{
printk
(
KERN_ERR
"mbx: DBG command received, but "
"dbg_buf has not been configured yet.
\n
"
);
return
;
}
if
(
dsp_mem_enable
(
dbg_buf
)
<
0
)
return
;
src
=
&
dbg_buf
[
dbg_rp
];
p
=
s
;
for
(
i
=
0
;
i
<
cnt
;
i
++
)
{
unsigned
short
tmp
;
/*
* Be carefull that dbg_buf should not be read with
* 1-byte access since it might be placed in DARAM/SARAM
* and it can cause unexpected byteswap.
* For example,
* *(p++) = *(src++) & 0xff;
* causes 1-byte access!
*/
tmp
=
*
src
++
;
*
(
p
++
)
=
tmp
&
0xff
;
if
(
*
(
p
-
1
)
==
'\n'
)
{
*
p
=
'\0'
;
printk
(
KERN_INFO
"%s"
,
s
);
p
=
s
;
continue
;
}
if
(
p
==
s_end
)
{
*
p
=
'\0'
;
printk
(
KERN_INFO
"%s
\n
"
,
s
);
p
=
s
;
continue
;
}
}
if
(
p
>
s
)
{
*
p
=
'\0'
;
printk
(
KERN_INFO
"%s
\n
"
,
s
);
}
if
((
dbg_rp
+=
cnt
+
1
)
>
dbg_buf_sz
-
dbg_line_sz
)
dbg_rp
=
0
;
dsp_mem_disable
(
dbg_buf
);
}
#ifdef OLD_BINARY_SUPPORT
static
void
mbx1_dbg_old
(
struct
mbcmd
*
mb
)
{
unsigned
char
tid
=
mb
->
cmd_l
;
char
s
[
80
],
*
s_end
=
&
s
[
79
],
*
p
;
...
...
@@ -2388,7 +2583,13 @@ void mbx1_dbg(struct mbcmd *mb)
}
buf
=
ipbuf_sys_da
->
d
;
cnt
=
buf
[
0
];
src
=
dspword_to_virt
(
MKLONG
(
buf
[
1
],
buf
[
2
]));
src
=
MKVIRT
(
buf
[
1
],
buf
[
2
]);
if
(
dsp_address_validate
(
src
,
cnt
,
"dbg buffer"
)
<
0
)
return
;
if
(
dsp_mem_enable
(
src
)
<
0
)
return
;
p
=
s
;
for
(
i
=
0
;
i
<
cnt
;
i
++
)
{
unsigned
short
tmp
;
...
...
@@ -2421,8 +2622,9 @@ void mbx1_dbg(struct mbcmd *mb)
}
release_ipbuf_pvt
(
ipbuf_sys_da
);
dsp_mem_disable
(
src
);
}
#endif
/* OLD_BINARY_SUPPORT */
/*
* sysfs files
...
...
@@ -2434,17 +2636,6 @@ static ssize_t devname_show(struct device *d, struct device_attribute *attr,
return
sprintf
(
buf
,
"%s
\n
"
,
dev
->
name
);
}
#define devstate_name(stat) (\
((stat) == OMAP_DSP_DEVSTATE_NOTASK) ? "NOTASK" :\
((stat) == OMAP_DSP_DEVSTATE_ATTACHED) ? "ATTACHED" :\
((stat) == OMAP_DSP_DEVSTATE_GARBAGE) ? "GARBAGE" :\
((stat) == OMAP_DSP_DEVSTATE_INVALID) ? "INVALID" :\
((stat) == OMAP_DSP_DEVSTATE_ADDREQ) ? "ADDREQ" :\
((stat) == OMAP_DSP_DEVSTATE_DELREQ) ? "DELREQ" :\
((stat) == OMAP_DSP_DEVSTATE_KILLREQ) ? "KILLREQ" :\
((stat) == OMAP_DSP_DEVSTATE_ADDFAIL) ? "ADDFAIL" :\
"unknown")
static
ssize_t
devstate_show
(
struct
device
*
d
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
...
...
@@ -2622,14 +2813,12 @@ int __init dsp_taskmod_init(void)
return
-
EINVAL
;
}
dsp_task_class
=
class_create
(
THIS_MODULE
,
"dsptask"
);
devfs_mk_dir
(
"dsptask"
);
return
0
;
}
void
dsp_taskmod_exit
(
void
)
{
devfs_remove
(
"dsptask"
);
class_destroy
(
dsp_task_class
);
driver_unregister
(
&
dsptask_driver
);
bus_unregister
(
&
dsptask_bus
);
...
...
arch/arm/plat-omap/dsp/taskwatch.c
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 200
4/12/01: DSP Gateway version 3.2
* 200
%/05/16: DSP Gateway version 3.3
*/
#include <linux/module.h>
...
...
@@ -83,7 +83,12 @@ static ssize_t dsp_twch_read(struct file *file, char *buf, size_t count,
count
=
devcount
*
sizeof
(
long
);
change_cnt
=
0
;
for
(
i
=
0
;
i
<
devcount
;
i
++
)
{
taskstat
[
i
]
=
taskdev_state
(
i
);
/*
* once the device state is read, the 'STALE' bit will be set
* so that the Dynamic Loader can distinguish the new request
* from the old one.
*/
taskstat
[
i
]
=
taskdev_state_stale
(
i
);
}
if
(
copy_to_user
(
buf
,
taskstat
,
count
))
...
...
arch/arm/plat-omap/dsp/uaccess_dsp.S
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
*
along
with
this
program
; if not, write to the Free Software
*
Foundation
,
Inc
.
,
59
Temple
Place
,
Suite
330
,
Boston
,
MA
02111
-
1307
USA
*
*
2004
/
06
/
29
:
DSP
Gateway
version
3
.
2
*
2004
/
06
/
29
:
DSP
Gateway
version
3
.
3
*/
#include <linux/linkage.h>
...
...
arch/arm/plat-omap/dsp/uaccess_dsp.h
View file @
b3ddf280
...
...
@@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2004/06/29: DSP Gateway version 3.
2
* 2004/06/29: DSP Gateway version 3.
3
*/
#ifndef _OMAP_DSP_UACCESS_DSP_H
...
...
arch/arm/plat-omap/mcbsp.c
View file @
b3ddf280
...
...
@@ -191,7 +191,7 @@ static int omap_mcbsp_check(unsigned int id)
static
void
omap_mcbsp_dsp_request
(
void
)
{
if
(
cpu_is_omap1510
()
||
cpu_is_omap16xx
())
{
omap_dsp_request_
idle
();
omap_dsp_request_
mem
();
clk_use
(
mcbsp_dsp_ck
);
clk_use
(
mcbsp_api_ck
);
...
...
@@ -210,6 +210,7 @@ static void omap_mcbsp_dsp_request(void)
static
void
omap_mcbsp_dsp_free
(
void
)
{
if
(
cpu_is_omap1510
()
||
cpu_is_omap16xx
())
{
omap_dsp_release_mem
();
clk_unuse
(
mcbsp_dspxor_ck
);
clk_unuse
(
mcbsp_dsp_ck
);
clk_unuse
(
mcbsp_api_ck
);
...
...
include/asm-arm/arch-omap/dsp.h
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2005/0
1/17: DSP Gateway version 3.2
* 2005/0
6/01: DSP Gateway version 3.3
*/
#ifndef ASM_ARCH_DSP_H
...
...
@@ -34,14 +34,16 @@
#define OMAP_DSP_IOCTL_RESET 1
#define OMAP_DSP_IOCTL_RUN 2
#define OMAP_DSP_IOCTL_SETRSTVECT 3
#define OMAP_DSP_IOCTL_IDLE 4
#define OMAP_DSP_IOCTL_
CPU_
IDLE 4
#define OMAP_DSP_IOCTL_MPUI_WORDSWAP_ON 5
#define OMAP_DSP_IOCTL_MPUI_WORDSWAP_OFF 6
#define OMAP_DSP_IOCTL_MPUI_BYTESWAP_ON 7
#define OMAP_DSP_IOCTL_MPUI_BYTESWAP_OFF 8
#define OMAP_DSP_IOCTL_GBL_IDLE 9
#define OMAP_DSP_IOCTL_DSPCFG 10
#define OMAP_DSP_IOCTL_DSPUNCFG 11
#define OMAP_DSP_IOCTL_TASKCNT 12
#define OMAP_DSP_IOCTL_POLL 13
#define OMAP_DSP_IOCTL_REGMEMR 40
#define OMAP_DSP_IOCTL_REGMEMW 41
#define OMAP_DSP_IOCTL_REGIOR 42
...
...
@@ -97,8 +99,12 @@ struct omap_dsp_mapinfo {
#define OMAP_DSP_DEVSTATE_INVALID 0x00000008
#define OMAP_DSP_DEVSTATE_ADDREQ 0x00000100
#define OMAP_DSP_DEVSTATE_DELREQ 0x00000200
#define OMAP_DSP_DEVSTATE_KILLREQ 0x00000400
#define OMAP_DSP_DEVSTATE_ADDFAIL 0x00001000
#define OMAP_DSP_DEVSTATE_ADDING 0x00010000
#define OMAP_DSP_DEVSTATE_DELING 0x00020000
#define OMAP_DSP_DEVSTATE_KILLING 0x00040000
#define OMAP_DSP_DEVSTATE_STATE_MASK 0x7fffffff
#define OMAP_DSP_DEVSTATE_STALE 0x80000000
struct
omap_dsp_taddinfo
{
unsigned
char
minor
;
...
...
@@ -133,7 +139,7 @@ struct omap_dsp_varinfo {
unsigned
short
val
[
0
];
};
#define OMAP_DSP_MBPROT_REVISION 0x001
8
#define OMAP_DSP_MBPROT_REVISION 0x001
9
#define OMAP_DSP_MBCMD_WDSND 0x10
#define OMAP_DSP_MBCMD_WDREQ 0x11
...
...
@@ -144,7 +150,8 @@ struct omap_dsp_varinfo {
#define OMAP_DSP_MBCMD_BKREQP 0x25
#define OMAP_DSP_MBCMD_TCTL 0x30
#define OMAP_DSP_MBCMD_TCTLDATA 0x31
#define OMAP_DSP_MBCMD_WDT 0x50
#define OMAP_DSP_MBCMD_POLL 0x32
#define OMAP_DSP_MBCMD_WDT 0x50
/* v3.3: obsolete */
#define OMAP_DSP_MBCMD_RUNLEVEL 0x51
#define OMAP_DSP_MBCMD_PM 0x52
#define OMAP_DSP_MBCMD_SUSPEND 0x53
...
...
@@ -217,6 +224,7 @@ struct omap_dsp_varinfo {
#define OMAP_DSP_EID_NOMEM 0xc0
#define OMAP_DSP_EID_NORES 0xc1
#define OMAP_DSP_EID_IPBFULL 0xc2
#define OMAP_DSP_EID_WDT 0xd0
#define OMAP_DSP_EID_TASKNOTRDY 0xe0
#define OMAP_DSP_EID_TASKBSY 0xe1
#define OMAP_DSP_EID_TASKERR 0xef
...
...
include/asm-arm/arch-omap/dsp_common.h
View file @
b3ddf280
...
...
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 200
4/09/22: DSP Gateway version 3.2
* 200
5/06/03: DSP Gateway version 3.3
*/
#ifndef ASM_ARCH_DSP_COMMON_H
...
...
@@ -29,6 +29,9 @@
void
omap_dsp_pm_suspend
(
void
);
void
omap_dsp_pm_resume
(
void
);
void
omap_dsp_request_idle
(
void
);
void
omap_dsp_request_mpui
(
void
);
void
omap_dsp_release_mpui
(
void
);
int
omap_dsp_request_mem
(
void
);
int
omap_dsp_release_mem
(
void
);
#endif
/* ASM_ARCH_DSP_COMMON_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