help
Enable 30MHz clock for OMAP CPU. If unsure, say N.
-source "arch/arm/plat-omap/dsp/Kconfig"
-
.pfn = __phys_to_pfn(L4_24XX_PHYS),
.length = L4_24XX_SIZE,
.type = MT_DEVICE
+ },
+ {
+ .virtual = DSP_MEM_24XX_VIRT,
+ .pfn = __phys_to_pfn(DSP_MEM_24XX_PHYS),
+ .length = DSP_MEM_24XX_SIZE,
+ .type = MT_DEVICE
+ },
+ {
+ .virtual = DSP_IPI_24XX_VIRT,
+ .pfn = __phys_to_pfn(DSP_IPI_24XX_PHYS),
+ .length = DSP_IPI_24XX_SIZE,
+ .type = MT_DEVICE
+ },
+ {
+ .virtual = DSP_MMU_24XX_VIRT,
+ .pfn = __phys_to_pfn(DSP_MMU_24XX_PHYS),
+ .length = DSP_MMU_24XX_SIZE,
+ .type = MT_DEVICE
}
};
to data on the serial RX line. This allows you to wake the
system from serial console.
+source "arch/arm/plat-omap/dsp/Kconfig"
+
endmenu
endif
obj-$(CONFIG_OMAP_GPIO_SWITCH) += gpio-switch.o
# DSP subsystem
-obj-y += dsp/
+obj-$(CONFIG_OMAP_DSP) += dsp/ mailbox.o
config OMAP_DSP
tristate "OMAP DSP driver (DSP Gateway)"
- depends on ARCH_OMAP15XX || ARCH_OMAP16XX
+ depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP24XX
help
This enables OMAP DSP driver, DSP Gateway.
/*
- * linux/arch/arm/mach-omap/dsp/dsp.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * Header for OMAP DSP driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/06/09: DSP Gateway version 3.3
*/
+#include <linux/platform_device.h>
#include "hardware_dsp.h"
#include "dsp_common.h"
+/*
+ * MAJOR device number: !! allocated arbitrary !!
+ */
+#define OMAP_DSP_CTL_MAJOR 96
+#define OMAP_DSP_TASK_MAJOR 97
+
#define OLD_BINARY_SUPPORT y
#ifdef OLD_BINARY_SUPPORT
#endif
#define DSP_INIT_PAGE 0xfff000
+
+#ifdef CONFIG_ARCH_OMAP1
/* idle program will be placed at IDLEPG_BASE. */
#define IDLEPG_BASE 0xfffe00
#define IDLEPG_SIZE 0x100
+#endif /* CONFIG_ARCH_OMAP1 */
/* timeout value for DSP response */
#define DSP_TIMEOUT (10 * HZ)
MEM_TYPE_EXTERN,
};
-enum arm_dsp_dir {
+enum arm_dsp_dir_e {
DIR_A2D,
DIR_D2A,
};
-/*
- * INT_D2A_MB value definition
- * INT_DSP_MAILBOX1: use Mailbox 1 (INT 10) for DSP->ARM mailbox
- * INT_DSP_MAILBOX2: use Mailbox 2 (INT 11) for DSP->ARM mailbox
- */
-#define INT_D2A_MB1 INT_DSP_MAILBOX1
+enum cfgstat_e {
+ CFGSTAT_CLEAN = 0,
+ CFGSTAT_READY,
+ CFGSTAT_SUSPEND,
+ CFGSTAT_RESUME, /* request only */
+ CFGSTAT_MAX
+};
-/* keep 2 entries for OMAP_DSP_TID_FREE and OMAP_DSP_TID_ANON */
+enum errcode_e {
+ ERRCODE_WDT = 0,
+ ERRCODE_MMU,
+ ERRCODE_MAX
+};
+
+/* keep 2 entries for TID_FREE and TID_ANON */
#define TASKDEV_MAX 254
+#define MK32(uw,lw) (((u32)(uw)) << 16 | (lw))
#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;
+ u16 da_dsp;
+ u16 da_arm;
+ u16 ad_dsp;
+ u16 ad_arm;
};
struct mem_sync_struct {
struct sync_seq *SDRAM;
};
-/* struct mbcmd and struct mbcmd_hw must be compatible */
+/* struct mbcmd and union mbcmd_hw must be compatible */
struct mbcmd {
- unsigned short cmd_l:8;
- unsigned short cmd_h:7;
- unsigned short seq:1;
- unsigned short data;
-};
-
-struct mbcmd_hw {
- unsigned short cmd;
- unsigned short data;
+ u32 data:16;
+ u32 cmd_l:8;
+ u32 cmd_h:7;
+ u32 seq:1;
};
-#define mbcmd_set(mb, h, l, d) \
- do { \
- (mb).cmd_h = (h); \
- (mb).cmd_l = (l); \
- (mb).data = (d); \
- } while(0)
+#define MBCMD_INIT(h, l, d) { \
+ .cmd_h = (h), \
+ .cmd_l = (l), \
+ .data = (d), \
+ }
struct mb_exarg {
- unsigned char tid;
+ u8 tid;
int argc;
- unsigned short *argv;
+ u16 *argv;
};
-extern void dsp_mb_start(void);
-extern void dsp_mb_stop(void);
-extern int dsp_mb_config(void *p);
-extern int sync_with_dsp(unsigned short *syncwd, unsigned short tid,
- int try_cnt);
-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);
+extern struct mbx *mbx_dsp;
+extern void dsp_mbx_start(void);
+extern void dsp_mbx_stop(void);
+extern int dsp_mbx_config(void *p);
+extern int sync_with_dsp(u16 *syncwd, u16 tid, int try_cnt);
+extern int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg,
+ int recovery_flag);
+#define dsp_mbcmd_send(mb) __dsp_mbcmd_send_exarg((mb), NULL, 0)
+#define dsp_mbcmd_send_exarg(mb, arg) __dsp_mbcmd_send_exarg((mb), (arg), 0)
+extern int dsp_mbcmd_send_and_wait_exarg(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)
-
+ dsp_mbcmd_send_and_wait_exarg((mb), NULL, (q))
+
+static __inline__ int __mbcompose_send_exarg(u8 cmd_h, u8 cmd_l, u16 data,
+ struct mb_exarg *arg,
+ int recovery_flag)
+{
+ struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
+ return __dsp_mbcmd_send_exarg(&mb, arg, recovery_flag);
+}
+#define mbcompose_send(cmd_h, cmd_l, data) \
+ __mbcompose_send_exarg(MBX_CMD_DSP_##cmd_h, (cmd_l), (data), NULL, 0)
+#define mbcompose_send_exarg(cmd_h, cmd_l, data, arg) \
+ __mbcompose_send_exarg(MBX_CMD_DSP_##cmd_h, (cmd_l), (data), arg, 0)
+#define mbcompose_send_recovery(cmd_h, cmd_l, data) \
+ __mbcompose_send_exarg(MBX_CMD_DSP_##cmd_h, (cmd_l), (data), NULL, 1)
+
+static __inline__ int __mbcompose_send_and_wait_exarg(u8 cmd_h, u8 cmd_l,
+ u16 data,
+ struct mb_exarg *arg,
+ wait_queue_head_t *q)
+{
+ struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
+ return dsp_mbcmd_send_and_wait_exarg(&mb, arg, q);
+}
+#define mbcompose_send_and_wait(cmd_h, cmd_l, data, q) \
+ __mbcompose_send_and_wait_exarg(MBX_CMD_DSP_##cmd_h, (cmd_l), (data), \
+ NULL, (q))
+#define mbcompose_send_and_wait_exarg(cmd_h, cmd_l, data, arg, q) \
+ __mbcompose_send_and_wait_exarg(MBX_CMD_DSP_##cmd_h, (cmd_l), (data), \
+ (arg), (q))
+
+extern struct ipbuf_head *bid_to_ipbuf(u16 bid);
extern void ipbuf_start(void);
extern void ipbuf_stop(void);
-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);
-extern void release_ipbuf(unsigned short bid);
+extern int ipbuf_config(u16 ln, u16 lsz, void *base);
+extern int ipbuf_sys_config(void *p, enum arm_dsp_dir_e dir);
+extern int ipbuf_p_validate(void *p, enum arm_dsp_dir_e dir);
+extern struct ipbuf_head *get_free_ipbuf(u8 tid);
+extern void release_ipbuf(struct ipbuf_head *ipb_h);
extern void balance_ipbuf(void);
+extern void unuse_ipbuf(struct ipbuf_head *ipb_h);
+extern void unuse_ipbuf_nowait(struct ipbuf_head *ipb_h);
#define release_ipbuf_pvt(ipbuf_pvt) \
do { \
- (ipbuf_pvt)->s = OMAP_DSP_TID_FREE; \
+ (ipbuf_pvt)->s = 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);
-extern int dsp_suspend(void);
-extern int dsp_resume(void);
+extern int dsp_cfgstat_request(enum cfgstat_e st);
+extern enum cfgstat_e dsp_cfgstat_get_stat(void);
+extern int dsp_set_runlevel(u8 level);
-extern int dsp_task_config_all(unsigned char n);
+extern int dsp_task_config_all(u8 n);
extern void dsp_task_unconfig_all(void);
-extern unsigned char dsp_task_count(void);
+extern u8 dsp_task_count(void);
extern int dsp_taskmod_busy(void);
extern int dsp_mkdev(char *name);
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 int dsp_tadd_minor(unsigned char minor, dsp_long_t adr);
+extern int dsp_tdel_minor(unsigned char minor);
+extern int dsp_tkill_minor(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 int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz);
extern void dsp_dbg_stop(void);
-extern int ipbuf_is_held(unsigned char tid, unsigned short bid);
+extern int ipbuf_is_held(u8 tid, u16 bid);
extern int dsp_mem_sync_inc(void);
extern int dsp_mem_sync_config(struct mem_sync_struct *sync);
extern int dsp_address_validate(void *p, size_t len, char *fmt, ...);
extern int dsp_mem_enable(void *adr);
extern void dsp_mem_disable(void *adr);
+#ifdef CONFIG_ARCH_OMAP1
extern void dsp_mem_usecount_clear(void);
+#endif
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_err_start(void);
extern void dsp_err_stop(void);
-extern void dsp_err_mmu_set(unsigned long adr);
-extern void dsp_err_mmu_clear(void);
-extern int dsp_err_mmu_isset(void);
-extern void dsp_err_wdt_clear(void);
-extern int dsp_err_wdt_isset(void);
+extern void dsp_err_set(enum errcode_e code, unsigned long arg);
+extern void dsp_err_clear(enum errcode_e code);
+extern int dsp_err_isset(enum errcode_e code);
-enum cmd_l_type {
+enum cmd_l_type_e {
CMD_L_TYPE_NULL,
CMD_L_TYPE_TID,
CMD_L_TYPE_SUBCMD,
struct cmdinfo {
char *name;
- enum cmd_l_type cmd_l_type;
+ enum cmd_l_type_e cmd_l_type;
void (*handler)(struct mbcmd *mb);
};
#define cmd_name(mb) (cmdinfo[(mb).cmd_h]->name)
extern char *subcmd_name(struct mbcmd *mb);
-extern void mblog_add(struct mbcmd *mb, enum arm_dsp_dir dir);
+extern void mblog_add(struct mbcmd *mb, enum arm_dsp_dir_e dir);
#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
-extern void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir dir);
+extern void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir_e dir);
#else /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
#define mblog_printcmd(mb, dir) do {} while(0)
#endif /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
-#ifdef CONFIG_PROC_FS
-extern struct proc_dir_entry *procdir_dsp;
-#endif /* CONFIG_PROC_FS */
-
extern struct platform_device dsp_device;
/*
- * linux/arch/arm/mach-omap/dsp/dsp_common.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * OMAP DSP driver static part
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/06/13: DSP Gateway version 3.3
*/
#include <linux/module.h>
-#include <linux/errno.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/tlbflush.h>
#include <asm/irq.h>
-#include <asm/arch/dsp.h>
+#ifdef CONFIG_ARCH_OMAP1
#include <asm/arch/tc.h>
+#endif
#include "dsp_common.h"
+#if defined(CONFIG_ARCH_OMAP1)
+#define dsp_boot_config(mode) omap_writew((mode), MPUI_DSP_BOOT_CONFIG)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define dsp_boot_config(mode) writel((mode), DSP_IPI_DSPBOOTCONFIG)
+#endif
+
+#if defined(CONFIG_ARCH_OMAP1)
struct clk *dsp_ck_handle;
struct clk *api_ck_handle;
-unsigned long dspmem_base, dspmem_size,
- daram_base, daram_size,
- saram_base, saram_size;
+#elif defined(CONFIG_ARCH_OMAP2)
+struct clk *dsp_fck_handle;
+struct clk *dsp_ick_handle;
+#endif
+dsp_long_t dspmem_base, dspmem_size,
+ daram_base, daram_size,
+ saram_base, saram_size;
struct cpustat {
struct mutex lock;
- enum e_cpustat stat;
- enum e_cpustat req;
- unsigned short icrmask;
+ enum cpustat_e stat;
+ enum cpustat_e req;
+ u16 icrmask;
+#ifdef CONFIG_ARCH_OMAP1
struct {
int mpui;
int mem;
} usecount;
int (*mem_req_cb)(void);
void (*mem_rel_cb)(void);
-};
-struct cpustat cpustat = {
+#endif
+} cpustat = {
.stat = CPUSTAT_RESET,
.icrmask = 0xffff,
};
-int dsp_set_rstvect(unsigned long adr)
+int dsp_set_rstvect(dsp_long_t adr)
{
unsigned long *dst_adr;
/* word swap */
*dst_adr = ((adr & 0xffff) << 16) | (adr >> 16);
/* fill 8 bytes! */
- *(dst_adr+1) = 0;
+ *(dst_adr + 1) = 0;
/* direct boot */
- omap_writew(MPUI_DSP_BOOT_CONFIG_DIRECT, MPUI_DSP_BOOT_CONFIG);
+ dsp_boot_config(DSP_BOOT_CONFIG_DIRECT);
return 0;
}
-static void simple_load_code(unsigned char *src_c, unsigned short *dst, int len)
+dsp_long_t dsp_get_rstvect(void)
+{
+ unsigned long *dst_adr;
+
+ dst_adr = dspbyte_to_virt(DSP_BOOT_ADR_DIRECT);
+ return ((*dst_adr & 0xffff) << 16) | (*dst_adr >> 16);
+}
+
+#ifdef CONFIG_ARCH_OMAP1
+static void simple_load_code(unsigned char *src_c, u16 *dst, int len)
{
int i;
- unsigned short *src = (unsigned short *)src_c;
+ u16 *src = (u16 *)src_c;
int len_w;
/* len must be multiple of 2. */
* DSP Gateway driver will overwrite this value with other value,
* to avoid confliction with the user program.
*/
-static unsigned long idle_boot_base = DSP_BOOT_ADR_MPUI;
+static dsp_long_t idle_boot_base = DSP_BOOT_ADR_MPUI;
static void dsp_gbl_idle(void)
{
clk_enable(api_ck_handle);
#if 0
- omap_writew(MPUI_DSP_BOOT_CONFIG_IDLE, MPUI_DSP_BOOT_CONFIG);
+ dsp_boot_config(DSP_BOOT_CONFIG_IDLE);
#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);
+ dsp_boot_config(DSP_BOOT_CONFIG_MPUI);
else
dsp_set_rstvect(idle_boot_base);
static void dsp_cpu_idle(void)
{
- unsigned short icr_tmp;
+ u16 icr_tmp;
unsigned char icrh, icrl;
__dsp_reset();
* DMA should not sleep for DARAM/SARAM access
* DPLL should not sleep while any other domain is active
*/
- icr_tmp = cpustat.icrmask & ~(DSPREG_ICR_DMA_IDLE_DOMAIN |
- DSPREG_ICR_DPLL_IDLE_DOMAIN);
+ icr_tmp = cpustat.icrmask & ~(DSPREG_ICR_DMA | DSPREG_ICR_DPLL);
icrh = icr_tmp >> 8;
icrl = icr_tmp & 0xff;
{
CPU_IDLE_TEXT_SIZE);
}
if (idle_boot_base == DSP_BOOT_ADR_MPUI)
- omap_writew(MPUI_DSP_BOOT_CONFIG_MPUI, MPUI_DSP_BOOT_CONFIG);
+ dsp_boot_config(DSP_BOOT_CONFIG_MPUI);
else
dsp_set_rstvect(idle_boot_base);
__dsp_run();
clk_disable(api_ck_handle);
}
-void dsp_set_idle_boot_base(unsigned long adr, size_t size)
+void dsp_set_idle_boot_base(dsp_long_t adr, size_t size)
{
if (adr == idle_boot_base)
return;
dsp_cpu_idle();
}
+void dsp_reset_idle_boot_base(void)
+{
+ idle_boot_base = DSP_BOOT_ADR_MPUI;
+}
+
+#endif /* CONFIG_ARCH_OMAP1 */
+
static int init_done;
static int __init omap_dsp_init(void)
saram_base = OMAP16XX_SARAM_BASE;
saram_size = OMAP16XX_SARAM_SIZE;
}
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+ if (cpu_is_omap24xx()) {
+ dspmem_base = DSP_MEM_24XX_VIRT;
+ dspmem_size = DSP_MEM_24XX_SIZE;
+ daram_base = OMAP24XX_DARAM_BASE;
+ daram_size = OMAP24XX_DARAM_SIZE;
+ saram_base = OMAP24XX_SARAM_BASE;
+ saram_size = OMAP24XX_SARAM_SIZE;
+ }
#endif
if (dspmem_size == 0) {
printk(KERN_ERR "omapdsp: unsupported omap architecture.\n");
return -ENODEV;
}
- dsp_ck_handle = clk_get(0, "dsp_ck");
+#if defined(CONFIG_ARCH_OMAP1)
+ dsp_ck_handle = clk_get(NULL, "dsp_ck");
if (IS_ERR(dsp_ck_handle)) {
printk(KERN_ERR "omapdsp: could not acquire dsp_ck handle.\n");
return PTR_ERR(dsp_ck_handle);
}
- api_ck_handle = clk_get(0, "api_ck");
+ api_ck_handle = clk_get(NULL, "api_ck");
if (IS_ERR(api_ck_handle)) {
printk(KERN_ERR "omapdsp: could not acquire api_ck handle.\n");
return PTR_ERR(api_ck_handle);
mpui_byteswap_off();
mpui_wordswap_on();
tc_wordswap();
+#elif defined(CONFIG_ARCH_OMAP2)
+ dsp_fck_handle = clk_get(NULL, "dsp_fck");
+ if (IS_ERR(dsp_fck_handle)) {
+ printk(KERN_ERR "omapdsp: could not acquire dsp_fck handle.\n");
+ return PTR_ERR(dsp_fck_handle);
+ }
+
+ dsp_ick_handle = clk_get(NULL, "dsp_ick");
+ if (IS_ERR(dsp_ick_handle)) {
+ printk(KERN_ERR "omapdsp: could not acquire dsp_ick handle.\n");
+ return PTR_ERR(dsp_ick_handle);
+ }
+#endif
init_done = 1;
printk(KERN_INFO "omap_dsp_init() done\n");
return 0;
}
+#if defined(CONFIG_ARCH_OMAP1)
static int dsp_late_init(void)
{
clk_disable(api_ck_handle);
return 0;
}
late_initcall(dsp_late_init);
+#endif
static void dsp_cpustat_update(void)
{
if (cpustat.req == CPUSTAT_RUN) {
if (cpustat.stat < CPUSTAT_RUN) {
+#if defined(CONFIG_ARCH_OMAP1)
__dsp_reset();
clk_enable(api_ck_handle);
udelay(10);
__dsp_run();
+#elif defined(CONFIG_ARCH_OMAP2)
+ __dsp_core_disable();
+ udelay(10);
+ __dsp_core_enable();
+#endif
cpustat.stat = CPUSTAT_RUN;
enable_irq(INT_DSP_MMU);
}
return;
}
- /* cpustat.stat < CPUSTAT_RUN */
+ /* cpustat.req < CPUSTAT_RUN */
if (cpustat.stat == CPUSTAT_RUN) {
disable_irq(INT_DSP_MMU);
+#ifdef CONFIG_ARCH_OMAP1
clk_disable(api_ck_handle);
+#endif
}
+#ifdef CONFIG_ARCH_OMAP1
/*
* (1) when ARM wants DARAM access, MPUI should be SAM and
* DSP needs to be on.
}
return;
}
+#endif /* CONFIG_ARCH_OMAP1 */
/*
* no user, no request
*/
if (cpustat.stat != CPUSTAT_RESET) {
+#if defined(CONFIG_ARCH_OMAP1)
__dsp_reset();
+#elif defined(CONFIG_ARCH_OMAP2)
+ __dsp_core_disable();
+#endif
cpustat.stat = CPUSTAT_RESET;
}
}
-void dsp_cpustat_request(enum e_cpustat req)
+void dsp_cpustat_request(enum cpustat_e req)
{
mutex_lock(&cpustat.lock);
cpustat.req = req;
mutex_unlock(&cpustat.lock);
}
-enum e_cpustat dsp_cpustat_get_stat(void)
+enum cpustat_e dsp_cpustat_get_stat(void)
{
return cpustat.stat;
}
-unsigned short dsp_cpustat_get_icrmask(void)
+u16 dsp_cpustat_get_icrmask(void)
{
return cpustat.icrmask;
}
-void dsp_cpustat_set_icrmask(unsigned short mask)
+void dsp_cpustat_set_icrmask(u16 mask)
{
mutex_lock(&cpustat.lock);
cpustat.icrmask = mask;
mutex_unlock(&cpustat.lock);
}
+#ifdef CONFIG_ARCH_OMAP1
void omap_dsp_request_mpui(void)
{
mutex_lock(&cpustat.lock);
cpustat.mem_rel_cb = NULL;
mutex_unlock(&cpustat.lock);
}
+#endif /* CONFIG_ARCH_OMAP1 */
/*
* Audio power control function prototypes and defaults
arch_initcall(omap_dsp_init);
+#ifdef CONFIG_ARCH_OMAP1
EXPORT_SYMBOL(omap_dsp_request_mpui);
EXPORT_SYMBOL(omap_dsp_release_mpui);
EXPORT_SYMBOL(omap_dsp_request_mem);
EXPORT_SYMBOL(omap_dsp_release_mem);
+#endif /* CONFIG_ARCH_OMAP1 */
#ifdef CONFIG_OMAP_DSP_MODULE
+#if defined(CONFIG_ARCH_OMAP1)
EXPORT_SYMBOL(dsp_ck_handle);
EXPORT_SYMBOL(api_ck_handle);
+#elif defined(CONFIG_ARCH_OMAP2)
+EXPORT_SYMBOL(dsp_fck_handle);
+EXPORT_SYMBOL(dsp_ick_handle);
+#endif
EXPORT_SYMBOL(dspmem_base);
EXPORT_SYMBOL(dspmem_size);
EXPORT_SYMBOL(daram_base);
EXPORT_SYMBOL(saram_base);
EXPORT_SYMBOL(saram_size);
EXPORT_SYMBOL(dsp_set_rstvect);
+EXPORT_SYMBOL(dsp_get_rstvect);
+#ifdef CONFIG_ARCH_OMAP1
EXPORT_SYMBOL(dsp_set_idle_boot_base);
+EXPORT_SYMBOL(dsp_reset_idle_boot_base);
+#endif /* CONFIG_ARCH_OMAP1 */
EXPORT_SYMBOL(dsp_cpustat_request);
EXPORT_SYMBOL(dsp_cpustat_get_stat);
EXPORT_SYMBOL(dsp_cpustat_get_icrmask);
EXPORT_SYMBOL(dsp_cpustat_set_icrmask);
+#ifdef CONFIG_ARCH_OMAP1
EXPORT_SYMBOL(dsp_register_mem_cb);
EXPORT_SYMBOL(dsp_unregister_mem_cb);
+#endif /* CONFIG_ARCH_OMAP1 */
EXPORT_SYMBOL(__cpu_flush_kern_tlb_range);
EXPORT_SYMBOL(cpu_architecture);
/*
- * linux/arch/arm/mach-omap/dsp/dsp_common.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * Header for OMAP DSP driver static part
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/06/13: DSP Gateway version 3.3
*/
+#ifndef DRIVER_DSP_COMMON_H
+#define DRIVER_DSP_COMMON_H
+
#include "hardware_dsp.h"
#define DSPSPACE_SIZE 0x1000000
do { omap_writel(omap_readl(r) | (b), (r)); } while(0)
#define omap_clr_bit_regl(b,r) \
do { omap_writel(omap_readl(r) & ~(b), (r)); } while(0)
+#define omap_set_bits_regl(val,mask,r) \
+ do { omap_writel((omap_readl(r) & ~(mask)) | (val), (r)); } while(0)
+
+#if defined(CONFIG_ARCH_OMAP15XX)
+#define INT_DSP_MMU INT_1510_DSP_MMU
+#elif defined(CONFIG_ARCH_OMAP16XX)
+#define INT_DSP_MMU INT_1610_DSP_MMU
+#elif defined(CONFIG_ARCH_OMAP24XX)
+#define INT_DSP_MMU INT_24XX_DSP_MMU
+#endif
#define dspword_to_virt(dw) ((void *)(dspmem_base + ((dw) << 1)))
#define dspbyte_to_virt(db) ((void *)(dspmem_base + (db)))
-#define virt_to_dspword(va) (((unsigned long)(va) - dspmem_base) >> 1)
-#define virt_to_dspbyte(va) ((unsigned long)(va) - dspmem_base)
+#define virt_to_dspword(va) \
+ ((dsp_long_t)(((unsigned long)(va) - dspmem_base) >> 1))
+#define virt_to_dspbyte(va) \
+ ((dsp_long_t)((unsigned long)(va) - dspmem_base))
#define is_dsp_internal_mem(va) \
(((unsigned long)(va) >= dspmem_base) && \
((unsigned long)(va) < dspmem_base + dspmem_size))
#define is_dspbyte_internal_mem(db) ((db) < dspmem_size)
#define is_dspword_internal_mem(dw) (((dw) << 1) < dspmem_size)
+#ifdef CONFIG_ARCH_OMAP1
/*
* MPUI byteswap/wordswap on/off
* 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)
+ omap_set_bits_regl(MPUI_CTRL_WORDSWAP_ALL, MPUI_CTRL_WORDSWAP_MASK, \
+ MPUI_CTRL)
#define mpui_wordswap_off() \
- do { \
- omap_writel( \
- (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_WORDSWAP_MASK) | \
- MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL); \
- } while(0)
+ omap_set_bits_regl(MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL_WORDSWAP_MASK, \
+ MPUI_CTRL)
#define mpui_byteswap_on() \
- do { \
- omap_writel( \
- (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_BYTESWAP_MASK) | \
- MPUI_CTRL_BYTESWAP_API, MPUI_CTRL); \
- } while(0)
+ omap_set_bits_regl(MPUI_CTRL_BYTESWAP_API, MPUI_CTRL_BYTESWAP_MASK, \
+ MPUI_CTRL)
#define mpui_byteswap_off() \
- do { \
- omap_writel( \
- (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_BYTESWAP_MASK) | \
- MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL); \
- } while(0)
+ omap_set_bits_regl(MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL_BYTESWAP_MASK, \
+ MPUI_CTRL)
/*
* TC wordswap on / off
TC_ENDIANISM); \
} while(0)
-#define tc_noswap() \
- do { \
- omap_writel(omap_readl(TC_ENDIANISM) & ~TC_ENDIANISM_EN, \
- TC_ENDIANISM); \
- } while(0)
+#define tc_noswap() omap_clr_bit_regl(TC_ENDIANISM_EN, TC_ENDIANISM)
/*
* enable priority registers, EMIF, MPUI control logic
#define __dsp_disable() omap_clr_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
#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)
+#endif /* CONFIG_ARCH_OMAP1 */
+#ifdef CONFIG_ARCH_OMAP2
+/*
+ * PRCM / IPI control logic
+ */
+#define RSTCTRL_RST1_DSP 0x00000001
+#define RSTCTRL_RST2_DSP 0x00000002
+#define __dsp_core_enable() \
+ do { RM_RSTCTRL_DSP &= ~RSTCTRL_RST1_DSP; } while (0)
+#define __dsp_core_disable() \
+ do { RM_RSTCTRL_DSP |= RSTCTRL_RST1_DSP; } while (0)
+#define __dsp_per_enable() \
+ do { RM_RSTCTRL_DSP &= ~RSTCTRL_RST2_DSP; } while (0)
+#define __dsp_per_disable() \
+ do { RM_RSTCTRL_DSP |= RSTCTRL_RST2_DSP; } while (0)
+#endif /* CONFIG_ARCH_OMAP2 */
+
+typedef u32 dsp_long_t; /* must have ability to carry TADD_ABORTADR */
+
+#if defined(CONFIG_ARCH_OMAP1)
extern struct clk *dsp_ck_handle;
extern struct clk *api_ck_handle;
-extern unsigned long dspmem_base, dspmem_size,
- daram_base, daram_size,
- saram_base, saram_size;
+#elif defined(CONFIG_ARCH_OMAP2)
+extern struct clk *dsp_fck_handle;
+extern struct clk *dsp_ick_handle;
+#endif
+extern dsp_long_t dspmem_base, dspmem_size,
+ daram_base, daram_size,
+ saram_base, saram_size;
-enum e_cpustat {
+enum cpustat_e {
CPUSTAT_RESET = 0,
- CPUSTAT_GBL_IDLE = 1,
- CPUSTAT_CPU_IDLE = 2,
- CPUSTAT_RUN = 3
+#ifdef CONFIG_ARCH_OMAP1
+ CPUSTAT_GBL_IDLE,
+ CPUSTAT_CPU_IDLE,
+#endif
+ CPUSTAT_RUN,
+ CPUSTAT_MAX
};
-#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_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);
+int dsp_set_rstvect(dsp_long_t adr);
+dsp_long_t dsp_get_rstvect(void);
+#ifdef CONFIG_ARCH_OMAP1
+void dsp_set_idle_boot_base(dsp_long_t adr, size_t size);
+void dsp_reset_idle_boot_base(void);
+#endif
+void dsp_cpustat_request(enum cpustat_e req);
+enum cpustat_e dsp_cpustat_get_stat(void);
+u16 dsp_cpustat_get_icrmask(void);
+void dsp_cpustat_set_icrmask(u16 mask);
+#ifdef CONFIG_ARCH_OMAP1
void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void));
void dsp_unregister_mem_cb(void);
+#endif
+
+#endif /* DRIVER_DSP_COMMON_H */
/*
- * linux/arch/arm/mach-omap/dsp/dsp_core.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * OMAP DSP driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/06/07: DSP Gateway version 3.3
*/
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
#include <linux/mutex.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/signal.h>
+#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/delay.h>
-#include <asm/irq.h>
+#include <asm/arch/mailbox.h>
#include <asm/arch/dsp_common.h>
-#include <asm/arch/dsp.h>
-#include "hardware_dsp.h"
+#include "dsp_mbcmd.h"
#include "dsp.h"
#include "ipbuf.h"
-
MODULE_AUTHOR("Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>");
MODULE_DESCRIPTION("OMAP DSP driver module");
MODULE_LICENSE("GPL");
-enum mbseq_check_level {
- MBSEQ_CHECK_NONE, /* no check */
- MBSEQ_CHECK_VERBOSE, /* discard the illegal command and
- error report */
- MBSEQ_CHECK_SILENT, /* discard the illegal command */
-};
-
-static enum mbseq_check_level mbseq_check_level = MBSEQ_CHECK_VERBOSE;
-
-static int mbx1_valid;
+struct mbx *mbx_dsp;
static struct sync_seq *mbseq;
-static unsigned short mbseq_expect_tmp;
-static unsigned short *mbseq_expect = &mbseq_expect_tmp;
+static u16 mbseq_expect_tmp;
+static u16 *mbseq_expect = &mbseq_expect_tmp;
/*
* mailbox commands
*/
-extern void mbx1_wdsnd(struct mbcmd *mb);
-extern void mbx1_wdreq(struct mbcmd *mb);
-extern void mbx1_bksnd(struct mbcmd *mb);
-extern void mbx1_bkreq(struct mbcmd *mb);
-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);
+extern void mbx_wdsnd(struct mbcmd *mb);
+extern void mbx_wdreq(struct mbcmd *mb);
+extern void mbx_bksnd(struct mbcmd *mb);
+extern void mbx_bkreq(struct mbcmd *mb);
+extern void mbx_bkyld(struct mbcmd *mb);
+extern void mbx_bksndp(struct mbcmd *mb);
+extern void mbx_bkreqp(struct mbcmd *mb);
+extern void mbx_tctl(struct mbcmd *mb);
+extern void mbx_poll(struct mbcmd *mb);
#ifdef OLD_BINARY_SUPPORT
/* v3.3 obsolete */
-extern void mbx1_wdt(struct mbcmd *mb);
+extern void mbx_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);
-extern void mbx1_tadd(struct mbcmd *mb);
-extern void mbx1_tdel(struct mbcmd *mb);
-extern void mbx1_dspcfg(struct mbcmd *mb);
-extern void mbx1_regrw(struct mbcmd *mb);
-extern void mbx1_getvar(struct mbcmd *mb);
-extern void mbx1_err(struct mbcmd *mb);
-extern void mbx1_dbg(struct mbcmd *mb);
+extern void mbx_suspend(struct mbcmd *mb);
+static void mbx_kfunc(struct mbcmd *mb);
+extern void mbx_tcfg(struct mbcmd *mb);
+extern void mbx_tadd(struct mbcmd *mb);
+extern void mbx_tdel(struct mbcmd *mb);
+extern void mbx_dspcfg(struct mbcmd *mb);
+extern void mbx_regrw(struct mbcmd *mb);
+extern void mbx_getvar(struct mbcmd *mb);
+extern void mbx_err(struct mbcmd *mb);
+extern void mbx_dbg(struct mbcmd *mb);
static const struct cmdinfo
- cif_null = { "Unknown", CMD_L_TYPE_NULL, NULL },
- cif_wdsnd = { "WDSND", CMD_L_TYPE_TID, mbx1_wdsnd },
- cif_wdreq = { "WDREQ", CMD_L_TYPE_TID, mbx1_wdreq },
- cif_bksnd = { "BKSND", CMD_L_TYPE_TID, mbx1_bksnd },
- cif_bkreq = { "BKREQ", CMD_L_TYPE_TID, mbx1_bkreq },
- cif_bkyld = { "BKYLD", CMD_L_TYPE_NULL, mbx1_bkyld },
- 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 },
+ cif_wdsnd = { "WDSND", CMD_L_TYPE_TID, mbx_wdsnd },
+ cif_wdreq = { "WDREQ", CMD_L_TYPE_TID, mbx_wdreq },
+ cif_bksnd = { "BKSND", CMD_L_TYPE_TID, mbx_bksnd },
+ cif_bkreq = { "BKREQ", CMD_L_TYPE_TID, mbx_bkreq },
+ cif_bkyld = { "BKYLD", CMD_L_TYPE_NULL, mbx_bkyld },
+ cif_bksndp = { "BKSNDP", CMD_L_TYPE_TID, mbx_bksndp },
+ cif_bkreqp = { "BKREQP", CMD_L_TYPE_TID, mbx_bkreqp },
+ cif_tctl = { "TCTL", CMD_L_TYPE_TID, mbx_tctl },
+ cif_poll = { "POLL", CMD_L_TYPE_NULL, mbx_poll },
#ifdef OLD_BINARY_SUPPORT
/* v3.3 obsolete */
- cif_wdt = { "WDT", CMD_L_TYPE_NULL, mbx1_wdt },
+ cif_wdt = { "WDT", CMD_L_TYPE_NULL, mbx_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 },
- cif_kfunc = { "KFUNC", CMD_L_TYPE_SUBCMD, mbx1_kfunc },
- cif_tcfg = { "TCFG", CMD_L_TYPE_TID, mbx1_tcfg },
- cif_tadd = { "TADD", CMD_L_TYPE_TID, mbx1_tadd },
- cif_tdel = { "TDEL", CMD_L_TYPE_TID, mbx1_tdel },
- cif_tstop = { "TSTOP", CMD_L_TYPE_TID, NULL },
- cif_dspcfg = { "DSPCFG", CMD_L_TYPE_SUBCMD, mbx1_dspcfg },
- cif_regrw = { "REGRW", CMD_L_TYPE_SUBCMD, mbx1_regrw },
- cif_getvar = { "GETVAR", CMD_L_TYPE_SUBCMD, mbx1_getvar },
- cif_setvar = { "SETVAR", CMD_L_TYPE_SUBCMD, NULL },
- cif_err = { "ERR", CMD_L_TYPE_SUBCMD, mbx1_err },
- cif_dbg = { "DBG", CMD_L_TYPE_NULL, mbx1_dbg };
-
-const struct cmdinfo *cmdinfo[128] = {
-/*00*/ &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, &cif_null, &cif_null, &cif_null,
-/*10*/ &cif_wdsnd, &cif_wdreq, &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, &cif_null,
-/*20*/ &cif_bksnd, &cif_bkreq, &cif_null, &cif_bkyld,
- &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_poll, &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,
-/*40*/ &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, &cif_null, &cif_null, &cif_null,
+ cif_runlevel = { "RUNLEVEL", CMD_L_TYPE_SUBCMD, NULL },
+ cif_pm = { "PM", CMD_L_TYPE_SUBCMD, NULL },
+ cif_suspend = { "SUSPEND", CMD_L_TYPE_NULL, mbx_suspend },
+ cif_kfunc = { "KFUNC", CMD_L_TYPE_SUBCMD, mbx_kfunc },
+ cif_tcfg = { "TCFG", CMD_L_TYPE_TID, mbx_tcfg },
+ cif_tadd = { "TADD", CMD_L_TYPE_TID, mbx_tadd },
+ cif_tdel = { "TDEL", CMD_L_TYPE_TID, mbx_tdel },
+ cif_tstop = { "TSTOP", CMD_L_TYPE_TID, NULL },
+ cif_dspcfg = { "DSPCFG", CMD_L_TYPE_SUBCMD, mbx_dspcfg },
+ cif_regrw = { "REGRW", CMD_L_TYPE_SUBCMD, mbx_regrw },
+ cif_getvar = { "GETVAR", CMD_L_TYPE_SUBCMD, mbx_getvar },
+ cif_setvar = { "SETVAR", CMD_L_TYPE_SUBCMD, NULL },
+ cif_err = { "ERR", CMD_L_TYPE_SUBCMD, mbx_err },
+ cif_dbg = { "DBG", CMD_L_TYPE_NULL, mbx_dbg };
+
+const struct cmdinfo *cmdinfo[MBX_CMD_MAX] = {
+ [MBX_CMD_DSP_WDSND] = &cif_wdsnd,
+ [MBX_CMD_DSP_WDREQ] = &cif_wdreq,
+ [MBX_CMD_DSP_BKSND] = &cif_bksnd,
+ [MBX_CMD_DSP_BKREQ] = &cif_bkreq,
+ [MBX_CMD_DSP_BKYLD] = &cif_bkyld,
+ [MBX_CMD_DSP_BKSNDP] = &cif_bksndp,
+ [MBX_CMD_DSP_BKREQP] = &cif_bkreqp,
+ [MBX_CMD_DSP_TCTL] = &cif_tctl,
+ [MBX_CMD_DSP_POLL] = &cif_poll,
#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,
+ [MBX_CMD_DSP_WDT] = &cif_wdt, /* v3.3 obsolete */
#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,
-/*60*/ &cif_tcfg, &cif_null, &cif_tadd, &cif_tdel,
- &cif_null, &cif_tstop, &cif_null, &cif_null,
- &cif_null, &cif_null, &cif_null, &cif_null,
- &cif_null, &cif_null, &cif_null, &cif_null,
-/*70*/ &cif_dspcfg, &cif_null, &cif_regrw, &cif_null,
- &cif_getvar, &cif_setvar, &cif_null, &cif_null,
- &cif_err, &cif_dbg, &cif_null, &cif_null,
- &cif_null, &cif_null, &cif_null, &cif_null
+ [MBX_CMD_DSP_RUNLEVEL] = &cif_runlevel,
+ [MBX_CMD_DSP_PM] = &cif_pm,
+ [MBX_CMD_DSP_SUSPEND] = &cif_suspend,
+ [MBX_CMD_DSP_KFUNC] = &cif_kfunc,
+ [MBX_CMD_DSP_TCFG] = &cif_tcfg,
+ [MBX_CMD_DSP_TADD] = &cif_tadd,
+ [MBX_CMD_DSP_TDEL] = &cif_tdel,
+ [MBX_CMD_DSP_TSTOP] = &cif_tstop,
+ [MBX_CMD_DSP_DSPCFG] = &cif_dspcfg,
+ [MBX_CMD_DSP_REGRW] = &cif_regrw,
+ [MBX_CMD_DSP_GETVAR] = &cif_getvar,
+ [MBX_CMD_DSP_SETVAR] = &cif_setvar,
+ [MBX_CMD_DSP_ERR] = &cif_err,
+ [MBX_CMD_DSP_DBG] = &cif_dbg,
};
-int sync_with_dsp(unsigned short *syncwd, unsigned short tid, int try_cnt)
+int sync_with_dsp(u16 *adr, u16 val, int try_cnt)
{
int try;
- if (*(volatile unsigned short *)syncwd == tid)
+ if (*(volatile u16 *)adr == val)
return 0;
for (try = 0; try < try_cnt; try++) {
udelay(1);
- if (*(volatile unsigned short *)syncwd == tid) {
+ if (*(volatile u16 *)adr == val) {
/* success! */
printk(KERN_INFO
"omapdsp: sync_with_dsp(): try = %d\n", try);
return -1;
}
-static __inline__ int mbsync_irq_save(unsigned long *flags, int try_cnt)
-{
- int cnt;
-
- local_irq_save(*flags);
- if (omap_readw(MAILBOX_ARM2DSP1_Flag) == 0)
- return 0;
- /*
- * mailbox is busy. wait for some usecs...
- */
- local_irq_restore(*flags);
- for (cnt = 0; cnt < try_cnt; cnt++) {
- udelay(1);
- local_irq_save(*flags);
- if (omap_readw(MAILBOX_ARM2DSP1_Flag) == 0) /* success! */
- return 0;
- local_irq_restore(*flags);
- }
-
- /* fail! */
- return -1;
-}
-
-#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
-#define print_mb_busy_abort(mb) \
- printk(KERN_DEBUG \
- "mbx: mailbox is busy. %s is aborting.\n", cmd_name(*mb))
-#define print_mb_mmu_abort(mb) \
- printk(KERN_DEBUG \
- "mbx: mmu interrupt is set. %s is aborting.\n", cmd_name(*mb))
-#else /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
-#define print_mb_busy_abort(mb) do {} while(0)
-#define print_mb_mmu_abort(mb) do {} while(0)
-#endif /* !CONFIG_OMAP_DSP_MBCMD_VERBOSE */
-
-int __mbcmd_send(struct mbcmd *mb)
-{
- struct mbcmd_hw *mb_hw = (struct mbcmd_hw *)mb;
- unsigned long flags;
-
- /*
- * DSP mailbox interrupt latency must be less than 1ms.
- */
- if (mbsync_irq_save(&flags, 1000) < 0) {
- print_mb_busy_abort(mb);
- return -1;
- }
-
- 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);
-
- local_irq_restore(flags);
- return 0;
-}
-
/*
- * __dsp_mbcmd_send(): mailbox dispatcher
+ * __dsp_mbcmd_send_exarg(): mailbox dispatcher
*/
-int __dsp_mbcmd_send(struct mbcmd *mb, struct mb_exarg *arg, int recovery_flag)
+int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg,
+ int recovery_flag)
{
static DEFINE_MUTEX(mbsend_lock);
int ret = 0;
* while MMU fault is set,
* only recovery command can be executed
*/
- if (dsp_err_mmu_isset() && !recovery_flag) {
- print_mb_mmu_abort(mb);
+ if (dsp_err_isset(ERRCODE_MMU) && !recovery_flag) {
+ printk(KERN_ERR
+ "mbx: mmu interrupt is set. %s is aborting.\n",
+ cmd_name(*mb));
return -1;
}
* 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) {
+ if (sync_with_dsp(&ipbuf_sys_ad->s, TID_FREE, 10) < 0) {
printk(KERN_ERR "omapdsp: ipbuf_sys_ad is busy.\n");
dsp_mem_disable(ipbuf_sys_ad);
ret = -EBUSY;
dsp_mem_disable(ipbuf_sys_ad);
}
- ret = __mbcmd_send(mb);
+ if (mbseq)
+ mbseq->ad_arm++;
+
+ mblog_add(mb, DIR_A2D);
+ mblog_printcmd(mb, DIR_A2D);
+
+ ret = mbx_send(mbx_dsp, *(mbx_msg_t *)mb);
out:
mutex_unlock(&mbsend_lock);
return ret;
}
-int __dsp_mbcmd_send_and_wait(struct mbcmd *mb, struct mb_exarg *arg,
- wait_queue_head_t *q)
+int dsp_mbcmd_send_and_wait_exarg(struct mbcmd *mb, struct mb_exarg *arg,
+ wait_queue_head_t *q)
{
long current_state;
DECLARE_WAITQUEUE(wait, current);
return 0;
}
-int __dsp_mbsend(unsigned char cmdh, unsigned char cmdl, unsigned short data,
- int recovery_flag)
+/*
+ * mbcmd receiver
+ */
+static void mbcmd_receiver(mbx_msg_t msg)
{
- struct mbcmd mb;
+ struct mbcmd *mb = (struct mbcmd *)&msg;
+
+ if (cmdinfo[mb->cmd_h] == NULL) {
+ printk(KERN_ERR
+ "invalid message (%08x) for mbcmd_receiver().\n", msg);
+ return;
+ }
+
+ (*mbseq_expect)++;
+
+ mblog_add(mb, DIR_D2A);
+ mblog_printcmd(mb, DIR_D2A);
- mbcmd_set(mb, cmdh, cmdl, data);
- return __dsp_mbcmd_send(&mb, NULL, recovery_flag);
+ /* call handler for the command */
+ if (cmdinfo[mb->cmd_h]->handler)
+ cmdinfo[mb->cmd_h]->handler(mb);
+ else
+ printk(KERN_ERR "mbx: %s is not allowed from DSP.\n",
+ cmd_name(*mb));
}
static int mbsync_hold_mem_active;
-void dsp_mb_start(void)
+void dsp_mbx_start(void)
{
- mbx1_valid = 1; /* start interpreting */
+ mbx_init_seq(mbx_dsp);
mbseq_expect_tmp = 0;
}
-void dsp_mb_stop(void)
+void dsp_mbx_stop(void)
{
- 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;
}
-int dsp_mb_config(void *p)
+int dsp_mbx_config(void *p)
{
unsigned long flags;
return 0;
}
-/*
- * mbq: mailbox queue
- */
-#define MBQ_DEPTH 16
-struct mbq {
- struct mbcmd mb[MBQ_DEPTH];
- int rp, wp, full;
-} mbq = {
- .rp = 0,
- .wp = 0,
-};
+static int __init dsp_mbx_init(void)
+{
+ int i;
+ int ret;
-#define mbq_inc(p) do { if (++(p) == MBQ_DEPTH) (p) = 0; } while(0)
+ for (i = 0; i < MBX_CMD_MAX; i++) {
+ if (cmdinfo[i] != NULL) {
+ ret = register_mbx_receiver(mbx_dsp, i, mbcmd_receiver);
+ if (ret)
+ goto fail;
+ }
+ }
-/*
- * workqueue for mbx1
- */
-static void do_mbx1(void)
-{
- int empty = 0;
+ return 0;
- disable_irq(INT_D2A_MB1);
- if ((mbq.rp == mbq.wp) && !mbq.full)
- empty = 1;
- enable_irq(INT_D2A_MB1);
+fail:
+ for (i--; i; i--)
+ unregister_mbx_receiver(mbx_dsp, i, mbcmd_receiver);
- while (!empty) {
- struct mbcmd *mb;
+ return ret;
+}
- mb = &mbq.mb[mbq.rp];
+static void dsp_mbx_exit(void)
+{
+ int i;
- mblog_add(mb, DIR_D2A);
- mblog_printcmd(mb, DIR_D2A);
+ for (i = 0; i < MBX_CMD_MAX; i++) {
+ if (cmdinfo[i] != NULL)
+ unregister_mbx_receiver(mbx_dsp, i, mbcmd_receiver);
+ }
- /*
- * call handler for each command
- */
- if (cmdinfo[mb->cmd_h]->handler)
- cmdinfo[mb->cmd_h]->handler(mb);
- else if (cmdinfo[mb->cmd_h] != &cif_null)
- printk(KERN_ERR "mbx: %s is not allowed from DSP.\n",
- cmd_name(*mb));
- else
- printk(KERN_ERR
- "mbx: Unrecognized command: "
- "cmd=0x%04x, data=0x%04x\n",
- ((struct mbcmd_hw *)mb)->cmd & 0x7fff, mb->data);
-
- disable_irq(INT_D2A_MB1);
- mbq_inc(mbq.rp);
- if (mbq.rp == mbq.wp)
- empty = 1;
- /* if mbq has been full, now we have a room. */
- if (mbq.full) {
- mbq.full = 0;
- enable_irq(INT_D2A_MB1);
- }
- enable_irq(INT_D2A_MB1);
+ if (mbsync_hold_mem_active) {
+ dsp_mem_disable((void *)daram_base);
+ mbsync_hold_mem_active = 0;
}
}
-static DECLARE_WORK(mbx1_work, (void (*)(void *))do_mbx1, NULL);
-
/*
* kernel function dispatcher
*/
-extern void mbx1_fbctl_upd(void);
-extern void mbx1_fbctl_disable(void);
+extern void mbx_fbctl_upd(void);
+extern void mbx_fbctl_disable(struct mbcmd *mb);
-static void mbx1_kfunc_fbctl(unsigned short data)
+static void mbx_kfunc_fbctl(struct mbcmd *mb)
{
- switch (data) {
- case OMAP_DSP_MBCMD_FBCTL_UPD:
- mbx1_fbctl_upd();
+ switch (mb->data) {
+ case FBCTL_UPD:
+ mbx_fbctl_upd();
break;
- case OMAP_DSP_MBCMD_FBCTL_DISABLE:
- mbx1_fbctl_disable();
+ case FBCTL_DISABLE:
+ mbx_fbctl_disable(mb);
break;
default:
printk(KERN_ERR
- "mailbox: Unknown FBCTL from DSP: 0x%04x\n", data);
+ "mbx: Unknown FBCTL from DSP: 0x%04x\n", mb->data);
}
}
-static void mbx1_kfunc_audio_pwr(unsigned short data)
+static void mbx_kfunc_audio_pwr(unsigned short data)
{
- struct mbcmd mb;
-
switch (data) {
- case OMAP_DSP_MBCMD_AUDIO_PWR_UP:
+ case AUDIO_PWR_UP:
omap_dsp_audio_pwr_up_request(0);
/* send back ack */
- mbcmd_set(mb, MBCMD(KFUNC), OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR,
- OMAP_DSP_MBCMD_AUDIO_PWR_UP);
- dsp_mbcmd_send(&mb);
+ mbcompose_send(KFUNC, KFUNC_AUDIO_PWR, AUDIO_PWR_UP);
break;
- case OMAP_DSP_MBCMD_AUDIO_PWR_DOWN1:
+ case AUDIO_PWR_DOWN1:
omap_dsp_audio_pwr_down_request(1);
break;
- case OMAP_DSP_MBCMD_AUDIO_PWR_DOWN2:
+ case AUDIO_PWR_DOWN2:
omap_dsp_audio_pwr_down_request(2);
break;
default:
}
}
-static void mbx1_kfunc(struct mbcmd *mb)
+static void mbx_kfunc(struct mbcmd *mb)
{
switch (mb->cmd_l) {
- case OMAP_DSP_MBCMD_KFUNC_FBCTL:
- mbx1_kfunc_fbctl(mb->data);
+ case KFUNC_FBCTL:
+ mbx_kfunc_fbctl(mb);
break;
- case OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR:
- mbx1_kfunc_audio_pwr(mb->data);
+ case KFUNC_AUDIO_PWR:
+ mbx_kfunc_audio_pwr(mb->data);
break;
default:
printk(KERN_ERR
- "mailbox: Unknown kfunc from DSP: 0x%02x\n", mb->cmd_l);
- }
-}
-
-/*
- * mailbox interrupt handler
- */
-static irqreturn_t mbx1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- union {
- struct mbcmd sw;
- struct mbcmd_hw hw;
- } *mb = (void *)&mbq.mb[mbq.wp];
-
-#if (INT_D2A_MB1 == INT_DSP_MAILBOX1)
- mb->hw.data = omap_readw(MAILBOX_DSP2ARM1);
- mb->hw.cmd = omap_readw(MAILBOX_DSP2ARM1b);
-#elif (INT_D2A_MB1 == INT_DSP_MAILBOX2)
- mb->hw.data = omap_readw(MAILBOX_DSP2ARM2);
- mb->hw.cmd = omap_readw(MAILBOX_DSP2ARM2b);
-#endif
-
- /* 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;
- case MBSEQ_CHECK_VERBOSE:
- printk(KERN_INFO
- "mbx: illegal seq bit!!! ignoring this command."
- " (%04x:%04x)\n", mb->hw.cmd, mb->hw.data);
- return IRQ_HANDLED;
- case MBSEQ_CHECK_SILENT:
- return IRQ_HANDLED;
- }
- }
-
- (*mbseq_expect)++;
-
- mbq_inc(mbq.wp);
- if (mbq.wp == mbq.rp) { /* mbq is full */
- mbq.full = 1;
- disable_irq(INT_D2A_MB1);
+ "mbx: Unknown KFUNC from DSP: 0x%02x\n", mb->cmd_l);
}
- schedule_work(&mbx1_work);
-
- return IRQ_HANDLED;
}
-static irqreturn_t mbx2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned short cmd, data;
-
-#if (INT_D2A_MB1 == INT_DSP_MAILBOX1)
- data = omap_readw(MAILBOX_DSP2ARM2);
- cmd = omap_readw(MAILBOX_DSP2ARM2b);
-#elif (INT_D2A_MB1 == INT_DSP_MAILBOX2)
- data = omap_readw(MAILBOX_DSP2ARM1);
- cmd = omap_readw(MAILBOX_DSP2ARM1b);
-#endif
- printk(KERN_DEBUG
- "mailbox2 interrupt! cmd=%04x, data=%04x\n", cmd, data);
-
- return IRQ_HANDLED;
-}
-
-#if 0
-static void mpuio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- printk(KERN_INFO "MPUIO interrupt!\n");
-}
-#endif
-
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry *procdir_dsp = NULL;
-
-static void dsp_create_procdir_dsp(void)
-{
- procdir_dsp = proc_mkdir("dsp", 0);
- if (procdir_dsp == NULL) {
- printk(KERN_ERR
- "omapdsp: failed to register proc directory: dsp\n");
- }
-}
-
-static void dsp_remove_procdir_dsp(void)
-{
- procdir_dsp = NULL;
- remove_proc_entry("dsp", 0);
-}
-#else /* CONFIG_PROC_FS */
-#define dsp_create_procdir_dsp() do { } while (0)
-#define dsp_remove_procdir_dsp() do { } while (0)
-#endif /* CONFIG_PROC_FS */
-
-extern irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id,
- struct pt_regs *regs);
-
extern int dsp_ctl_core_init(void);
extern void dsp_ctl_core_exit(void);
extern void dsp_ctl_init(void);
/*
* driver functions
*/
-#if (INT_D2A_MB1 == INT_DSP_MAILBOX1)
-# define INT_D2A_MB2 INT_DSP_MAILBOX2
-#elif(INT_D2A_MB1 == INT_DSP_MAILBOX2) /* swap MB1 and MB2 */
-# define INT_D2A_MB2 INT_DSP_MAILBOX1
-#endif
-
static int __init dsp_drv_probe(struct platform_device *pdev)
{
int ret;
printk(KERN_INFO "OMAP DSP driver initialization\n");
-
- //__dsp_enable(); // XXX
-
- dsp_create_procdir_dsp();
+#ifdef CONFIG_ARCH_OMAP2
+ clk_enable(dsp_fck_handle);
+ clk_enable(dsp_ick_handle);
+ __dsp_per_enable();
+#endif
if ((ret = dsp_ctl_core_init()) < 0)
goto fail1;
mblog_init();
if ((ret = dsp_taskmod_init()) < 0)
goto fail3;
-
- /*
- * mailbox interrupt handlers registration
- */
- ret = request_irq(INT_D2A_MB1, mbx1_interrupt, SA_INTERRUPT, "dsp",
- &pdev->dev);
- if (ret) {
- printk(KERN_ERR
- "failed to register mailbox1 interrupt: %d\n", ret);
+ if ((ret = dsp_mbx_init()) < 0)
goto fail4;
- }
-
- ret = request_irq(INT_D2A_MB2, mbx2_interrupt, SA_INTERRUPT, "dsp",
- &pdev->dev);
- if (ret) {
- printk(KERN_ERR
- "failed to register mailbox2 interrupt: %d\n", ret);
- goto fail5;
- }
-
- ret = request_irq(INT_DSP_MMU, dsp_mmu_interrupt, SA_INTERRUPT, "dsp",
- &pdev->dev);
- if (ret) {
- printk(KERN_ERR
- "failed to register DSP MMU interrupt: %d\n", ret);
- 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) {
- printk(KERN_ERR
- "failed to register MPUIO interrupt: %d\n", ret);
- goto fail7;
- }
-#endif
return 0;
-fail6:
- free_irq(INT_D2A_MB2, &pdev->dev);
-fail5:
- free_irq(INT_D2A_MB1, &pdev->dev);
fail4:
dsp_taskmod_exit();
fail3:
fail2:
dsp_ctl_core_exit();
fail1:
- dsp_remove_procdir_dsp();
-
- //__dsp_disable(); // XXX
+#ifdef CONFIG_ARCH_OMAP2
+ __dsp_per_disable();
+ clk_disable(dsp_ick_handle);
+ clk_disable(dsp_fck_handle);
+#endif
return ret;
}
{
dsp_cpustat_request(CPUSTAT_RESET);
-#if 0
- free_irq(INT_MPUIO, dev);
-#endif
- free_irq(INT_DSP_MMU, &pdev->dev);
- free_irq(INT_D2A_MB2, &pdev->dev);
- free_irq(INT_D2A_MB1, &pdev->dev);
-
- /* recover disable_depth */
- enable_irq(INT_DSP_MMU);
-
- dspuncfg();
+ dsp_cfgstat_request(CFGSTAT_CLEAN);
+ dsp_mbx_exit();
dsp_taskmod_exit();
mblog_exit();
dsp_ctl_exit();
dsp_mem_exit();
dsp_ctl_core_exit();
- dsp_remove_procdir_dsp();
-
- //__dsp_disable(); // XXX
+#ifdef CONFIG_ARCH_OMAP2
+ __dsp_per_disable();
+ clk_disable(dsp_ick_handle);
+ clk_disable(dsp_fck_handle);
+#endif
return 0;
}
#ifdef CONFIG_PM
static int dsp_drv_suspend(struct platform_device *pdev, pm_message_t state)
{
- dsp_suspend();
+ dsp_cfgstat_request(CFGSTAT_SUSPEND);
return 0;
}
static int dsp_drv_resume(struct platform_device *pdev)
{
- dsp_resume();
+ dsp_cfgstat_request(CFGSTAT_RESUME);
return 0;
}
#endif /* CONFIG_PM */
static struct resource dsp_resources[] = {
- {
- .start = INT_DSP_MAILBOX1,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = INT_DSP_MAILBOX2,
- .flags = IORESOURCE_IRQ,
- },
{
.start = INT_DSP_MMU,
.flags = IORESOURCE_IRQ,
{
int ret;
+ mbx_dsp = mbx_get("DSP");
+ if (IS_ERR(mbx_dsp)) {
+ printk(KERN_ERR "failed to get mailbox handler for DSP.\n");
+ goto fail1;
+ }
+
ret = platform_device_register(&dsp_device);
if (ret) {
printk(KERN_ERR "failed to register the DSP device: %d\n", ret);
/*
- * linux/arch/arm/mach-omap/dsp/dsp_ctl.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * OMAP DSP control device driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/06/09: DSP Gateway version 3.3
*/
#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/major.h>
#include <linux/fs.h>
#include <linux/device.h>
-#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/ioctls.h>
-#include <asm/arch/dsp.h>
+#include <asm/arch/mailbox.h>
#include "hardware_dsp.h"
+#include "dsp_mbcmd.h"
#include "dsp.h"
#include "ipbuf.h"
+#include "ioctl.h"
+
+enum dsp_space_e {
+ SPACE_MEM,
+ SPACE_IO,
+};
+
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+static enum fbstat_e {
+ FBSTAT_DISABLED = 0,
+ FBSTAT_ENABLED,
+ FBSTAT_MAX,
+} fbstat = FBSTAT_ENABLED;
+#endif
+
+static enum cfgstat_e cfgstat;
+int mbx_revision;
+static u8 n_stask;
+static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count);
static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
char *buf);
-static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
-extern struct device_attribute dev_attr_ipbuf;
-
-static enum cfgstat {
- CFG_ERR,
- CFG_READY,
- CFG_SUSPEND
-} cfgstat;
-int mbx_revision;
-static DECLARE_WAIT_QUEUE_HEAD(ioctl_wait_q);
-static unsigned short ioctl_wait_cmd;
-static DEFINE_MUTEX(ioctl_lock);
-static unsigned char n_stask;
+#define __ATTR_RW(_name, _mode) { \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
+ .show = _name##_show, \
+ .store = _name##_store, \
+}
+
+static struct device_attribute dev_attr_ifver = __ATTR_RO(ifver);
+static struct device_attribute dev_attr_cpustat = __ATTR_RO(cpustat);
+static struct device_attribute dev_attr_icrmask = __ATTR_RW(icrmask, 0644);
+static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
/*
- * control functions
+ * misc interactive mailbox command operations
*/
-static short varread_val[5]; /* maximum */
+static struct misc_mb_wait_struct {
+ struct mutex lock;
+ wait_queue_head_t wait_q;
+ u8 cmd_h;
+ u8 cmd_l;
+ u16 *retvp;
+} misc_mb_wait = {
+ .lock = __MUTEX_INITIALIZER(misc_mb_wait.lock),
+ .wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(misc_mb_wait.wait_q),
+};
-static int dsp_regread(unsigned short cmd_l, unsigned short adr,
- unsigned short *val)
+static int __misc_mbcompose_send_and_wait(u8 cmd_h, u8 cmd_l, u16 data,
+ u16 *retvp)
{
- struct mbcmd mb;
+ struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
int ret = 0;
- if (mutex_lock_interruptible(&ioctl_lock))
- return -ERESTARTSYS;
+ if (mutex_lock_interruptible(&misc_mb_wait.lock))
+ return -EINTR;
- ioctl_wait_cmd = MBCMD(REGRW);
- mbcmd_set(mb, MBCMD(REGRW), cmd_l, adr);
- dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+ misc_mb_wait.cmd_h = mb.cmd_h;
+ misc_mb_wait.cmd_l = mb.cmd_l;
+ misc_mb_wait.retvp = retvp;
+ dsp_mbcmd_send_and_wait(&mb, &misc_mb_wait.wait_q);
- if (ioctl_wait_cmd != 0) {
- printk(KERN_ERR "omapdsp: register read error!\n");
+ if (misc_mb_wait.cmd_h != 0)
ret = -EINVAL;
- goto up_out;
+
+ mutex_unlock(&misc_mb_wait.lock);
+ return ret;
+}
+
+#define misc_mbcompose_send_and_wait(cmd_h, cmd_l, data, retvp) \
+ __misc_mbcompose_send_and_wait(MBX_CMD_DSP_##cmd_h, (cmd_l), \
+ (data), (retvp));
+
+static int misc_mbcmd_response(struct mbcmd *mb, int argc, int match_cmd_l_flag)
+{
+ volatile u16 *buf;
+ int i;
+
+ /* if match_cmd_l_v flag is set, cmd_l needs to be matched as well. */
+ if (!waitqueue_active(&misc_mb_wait.wait_q) ||
+ (misc_mb_wait.cmd_h != mb->cmd_h) ||
+ (match_cmd_l_flag && (misc_mb_wait.cmd_l != mb->cmd_l))) {
+ const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
+ char cmdstr[32];
+
+ if (ci->cmd_l_type == CMD_L_TYPE_SUBCMD)
+ sprintf(cmdstr, "%s:%s", ci->name, subcmd_name(mb));
+ else
+ strcpy(cmdstr, ci->name);
+ printk(KERN_WARNING
+ "mbx: unexpected command %s received!\n", cmdstr);
+ return -1;
+ }
+
+ /*
+ * if argc == 1, receive data through mbx:data register.
+ * if argc > 1, receive through ipbuf_sys.
+ */
+ if (argc == 1)
+ misc_mb_wait.retvp[0] = mb->data;
+ else if (argc > 1) {
+ if (dsp_mem_enable(ipbuf_sys_da) < 0) {
+ printk(KERN_ERR "mbx: %s - ipbuf_sys_da read failed!\n",
+ cmdinfo[mb->cmd_h]->name);
+ return -1;
+ }
+ if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) {
+ printk(KERN_ERR "mbx: %s - IPBUF sync failed!\n",
+ cmdinfo[mb->cmd_h]->name);
+ dsp_mem_disable(ipbuf_sys_da);
+ return -1;
+ }
+ /* need word access. do not use memcpy. */
+ buf = ipbuf_sys_da->d;
+ for (i = 0; i < argc; i++)
+ misc_mb_wait.retvp[i] = buf[i];
+ release_ipbuf_pvt(ipbuf_sys_da);
+ dsp_mem_disable(ipbuf_sys_da);
}
- *val = varread_val[0];
+ misc_mb_wait.cmd_h = 0;
+ wake_up_interruptible(&misc_mb_wait.wait_q);
+ return 0;
+}
+
+static int dsp_regread(enum dsp_space_e space, u16 adr, u16 *val)
+{
+ u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMR : REGRW_IOR;
+ int ret;
+
+ ret = misc_mbcompose_send_and_wait(REGRW, cmd_l, adr, val);
+ if ((ret < 0) && (ret != -EINTR))
+ printk(KERN_ERR "omapdsp: register read error!\n");
-up_out:
- mutex_unlock(&ioctl_lock);
return ret;
}
-static int dsp_regwrite(unsigned short cmd_l, unsigned short adr,
- unsigned short val)
+static int dsp_regwrite(enum dsp_space_e space, u16 adr, u16 val)
{
- struct mbcmd mb;
+ u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMW : REGRW_IOW;
struct mb_exarg arg = {
- .tid = OMAP_DSP_TID_ANON,
+ .tid = TID_ANON,
.argc = 1,
.argv = &val,
};
- mbcmd_set(mb, MBCMD(REGRW), cmd_l, adr);
- dsp_mbcmd_send_exarg(&mb, &arg);
+ mbcompose_send_exarg(REGRW, cmd_l, adr, &arg);
return 0;
}
-static int dsp_getvar(unsigned char varid, unsigned short *val, int sz)
+static int dsp_getvar(u8 varid, u16 *val)
{
- struct mbcmd mb;
- int ret = 0;
-
- if (mutex_lock_interruptible(&ioctl_lock))
- return -ERESTARTSYS;
-
- ioctl_wait_cmd = MBCMD(GETVAR);
- mbcmd_set(mb, MBCMD(GETVAR), varid, 0);
- dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+ int ret;
- if (ioctl_wait_cmd != 0) {
+ ret = misc_mbcompose_send_and_wait(GETVAR, varid, 0, val);
+ if ((ret < 0) && (ret != -EINTR))
printk(KERN_ERR "omapdsp: variable read error!\n");
- ret = -EINVAL;
- goto up_out;
- }
-
- memcpy(val, varread_val, sz * sizeof(short));
-up_out:
- mutex_unlock(&ioctl_lock);
return ret;
}
-static int dsp_setvar(unsigned char varid, unsigned short val)
+static int dsp_setvar(u8 varid, u16 val)
{
- dsp_mbsend(MBCMD(SETVAR), varid, val);
+ mbcompose_send(SETVAR, varid, val);
return 0;
}
-static int dspcfg(void)
+/*
+ * dsp_cfg() return value
+ * = 0: OK
+ * = 1: failed, but state is clear. (DSPCFG command failed)
+ * < 0: failed. need cleanup.
+ */
+static int dsp_cfg(void)
{
- struct mbcmd mb;
int ret = 0;
- if (mutex_lock_interruptible(&ioctl_lock))
- return -ERESTARTSYS;
-
- if (cfgstat != CFG_ERR) {
- printk(KERN_ERR
- "omapdsp: DSP has been already configured. "
- "do unconfig!\n");
- ret = -EBUSY;
- goto up_out;
- }
-
+#ifdef CONFIG_ARCH_OMAP1
/* for safety */
dsp_mem_usecount_clear();
+#endif
/*
* DSPCFG command and dsp_mem_start() must be called
*/
dsp_mem_enable((void *)dspmem_base);
- dsp_mb_start();
+ dsp_mbx_start();
dsp_twch_start();
dsp_mem_start();
dsp_err_start();
mbx_revision = -1;
- ioctl_wait_cmd = MBCMD(DSPCFG);
- mbcmd_set(mb, MBCMD(DSPCFG), OMAP_DSP_MBCMD_DSPCFG_REQ, 0);
- dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
- if (ioctl_wait_cmd != 0) {
- printk(KERN_ERR "omapdsp: configuration error!\n");
- ret = -EINVAL;
- cfgstat = CFG_ERR;
- goto up_out;
+ ret = misc_mbcompose_send_and_wait(DSPCFG, DSPCFG_REQ, 0, NULL);
+ if (ret < 0) {
+ if (ret != -EINTR)
+ printk(KERN_ERR "omapdsp: configuration error!\n");
+ ret = 1;
+ goto out;
}
-#ifdef OLD_BINARY_SUPPORT
+#if defined(CONFIG_ARCH_OMAP1) && defined(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);
+ if ((ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA)) < 0)
+ goto out;
}
#endif
- if ((ret = dsp_task_config_all(n_stask)) < 0) {
- mutex_unlock(&ioctl_lock);
- dspuncfg();
- dsp_mem_disable((void *)dspmem_base);
- return -EINVAL;
- }
+ if ((ret = dsp_task_config_all(n_stask)) < 0)
+ goto out;
- cfgstat = CFG_READY;
+ /* initialization */
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+ fbstat = FBSTAT_ENABLED;
+#endif
/* send parameter */
- if ((ret = dsp_setvar(OMAP_DSP_MBCMD_VARID_ICRMASK,
- dsp_cpustat_get_icrmask())) < 0)
- goto up_out;
+ if ((ret = dsp_setvar(VARID_ICRMASK, dsp_cpustat_get_icrmask())) < 0)
+ goto out;
/* create runtime sysfs entries */
device_create_file(&dsp_device.dev, &dev_attr_loadinfo);
- device_create_file(&dsp_device.dev, &dev_attr_ipbuf);
-up_out:
+out:
dsp_mem_disable((void *)dspmem_base);
- mutex_unlock(&ioctl_lock);
return ret;
}
-int dspuncfg(void)
+static int dsp_uncfg(void)
{
if (dsp_taskmod_busy()) {
printk(KERN_WARNING "omapdsp: tasks are busy.\n");
return -EBUSY;
}
- if (mutex_lock_interruptible(&ioctl_lock))
- return -ERESTARTSYS;
-
/* FIXME: lock task module */
/* remove runtime sysfs entries */
device_remove_file(&dsp_device.dev, &dev_attr_loadinfo);
- device_remove_file(&dsp_device.dev, &dev_attr_ipbuf);
- dsp_mb_stop();
+ dsp_mbx_stop();
dsp_twch_stop();
dsp_mem_stop();
dsp_err_stop();
dsp_dbg_stop();
dsp_task_unconfig_all();
ipbuf_stop();
- cfgstat = CFG_ERR;
- mutex_unlock(&ioctl_lock);
return 0;
}
-int dsp_is_ready(void)
+static int dsp_suspend(void)
{
- return (cfgstat == CFG_READY) ? 1 : 0;
+ int ret;
+
+ ret = misc_mbcompose_send_and_wait(SUSPEND, 0, 0, NULL);
+ if (ret < 0) {
+ if (ret != -EINVAL)
+ printk(KERN_ERR "omapdsp: DSP suspend error!\n");
+ return ret;
+ }
+
+ udelay(100); /* wait for DSP-side execution */
+ return 0;
}
-/*
- * polls all tasks
- */
-int dsp_poll(void)
+int dsp_cfgstat_request(enum cfgstat_e st_req)
{
- struct mbcmd mb;
- int ret = 0;
+ static DEFINE_MUTEX(cfgstat_lock);
+ int ret = 0, ret_override = 0;
- if (mutex_lock_interruptible(&ioctl_lock))
- return -ERESTARTSYS;
+ if (mutex_lock_interruptible(&cfgstat_lock))
+ return -EINTR;
- ioctl_wait_cmd = MBCMD(POLL);
- mbcmd_set(mb, MBCMD(POLL), 0, 0);
- dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+again:
+ switch (st_req) {
- if (ioctl_wait_cmd != 0) {
- printk(KERN_ERR "omapdsp: poll error!\n");
- ret = -EINVAL;
- goto up_out;
- }
+ /* cfgstat takes CLEAN, READY or SUSPEND,
+ while st_req can take SUSPEND in addition. */
-up_out:
- mutex_unlock(&ioctl_lock);
- return ret;
-}
+ case CFGSTAT_CLEAN:
+ if (cfgstat == CFGSTAT_CLEAN)
+ goto up_out;
+ if ((ret = dsp_uncfg()) < 0)
+ goto up_out;
+ break;
-void dsp_runlevel(unsigned char level)
-{
- if (level == OMAP_DSP_MBCMD_RUNLEVEL_RECOVERY)
- dsp_mbsend_recovery(MBCMD(RUNLEVEL), level, 0);
- else
- dsp_mbsend(MBCMD(RUNLEVEL), level, 0);
-}
+ case CFGSTAT_READY:
+ if (cfgstat != CFGSTAT_CLEAN) {
+ printk(KERN_ERR "omapdsp: DSP is ready already!\n");
+ ret = -EINVAL;
+ goto up_out;
+ }
-static enum cfgstat cfgstat_save_suspend;
+ ret = dsp_cfg();
+ if (ret > 0) { /* failed, but state is clear. */
+ ret = -EINVAL;
+ goto up_out;
+ } else if (ret < 0) { /* failed, need cleanup. */
+ st_req = CFGSTAT_CLEAN;
+ ret_override = ret;
+ goto again;
+ }
+ break;
+
+ /*
+ * suspend / resume
+ * DSP is not reset within this code, but done in omap_pm_suspend.
+ * so if these functions are called from sysfs,
+ * DSP should be reset / unreset out of these functions.
+ */
+ case CFGSTAT_SUSPEND:
+ switch (cfgstat) {
+
+ case CFGSTAT_CLEAN:
+ if (dsp_cpustat_get_stat() == CPUSTAT_RUN) {
+ printk(KERN_WARNING
+ "omapdsp: illegal operation -- trying "
+ "suspend DSP while it is running but "
+ "not configured.\n"
+ " Resetting DSP.\n");
+ dsp_cpustat_request(CPUSTAT_RESET);
+ ret = -EINVAL;
+ }
+ goto up_out;
-/*
- * 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;
+ case CFGSTAT_READY:
+ if ((ret = dsp_suspend()) < 0)
+ goto up_out;
+ break;
- if (cfgstat == CFG_SUSPEND) {
- printk(KERN_ERR "omapdsp: DSP is already in suspend state.\n");
- return -EINVAL;
- }
+ case CFGSTAT_SUSPEND:
+ goto up_out;
- if (mutex_lock_interruptible(&ioctl_lock))
- return -ERESTARTSYS;
+ default:
+ BUG();
- cfgstat_save_suspend = cfgstat;
- if (!dsp_is_ready()) {
- 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_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+ break;
+
+ case CFGSTAT_RESUME:
+ if (cfgstat != CFGSTAT_SUSPEND) {
+ printk(KERN_WARNING
+ "omapdsp: DSP resume request, but DSP is not in "
+ "suspend state.\n");
+ ret = -EINVAL;
+ goto up_out;
+ }
+ st_req = CFGSTAT_READY;
+ break;
+
+ default:
+ BUG();
- if (ioctl_wait_cmd != 0) {
- printk(KERN_ERR "omapdsp: DSP suspend error!\n");
- ret = -EINVAL;
- goto up_out;
}
- udelay(100);
-transition:
- cfgstat = CFG_SUSPEND;
+ cfgstat = st_req;
up_out:
- mutex_unlock(&ioctl_lock);
+ mutex_unlock(&cfgstat_lock);
+ return ret_override ? ret_override : ret;
+}
+
+enum cfgstat_e dsp_cfgstat_get_stat(void)
+{
+ return cfgstat;
+}
+
+/*
+ * polls all tasks
+ */
+static int dsp_poll(void)
+{
+ int ret;
+
+ ret = misc_mbcompose_send_and_wait(POLL, 0, 0, NULL);
+ if ((ret < 0) && (ret != -EINTR))
+ printk(KERN_ERR "omapdsp: poll error!\n");
+
return ret;
}
-int dsp_resume(void)
+int dsp_set_runlevel(u8 level)
{
- if (cfgstat != CFG_SUSPEND) {
- printk(KERN_ERR "omapdsp: DSP is not in suspend state.\n");
- return -EINVAL;
+ if (level == RUNLEVEL_RECOVERY) {
+ if (mbcompose_send_recovery(RUNLEVEL, level, 0) < 0)
+ return -EINVAL;
+ } else {
+ if ((level < RUNLEVEL_USER) ||
+ (level > RUNLEVEL_SUPER))
+ return -EINVAL;
+ if (mbcompose_send(RUNLEVEL, level, 0) < 0)
+ return -EINVAL;
}
- cfgstat = cfgstat_save_suspend;
return 0;
}
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
static void dsp_fbctl_enable(void)
{
- dsp_mbsend(MBCMD(KFUNC), OMAP_DSP_MBCMD_KFUNC_FBCTL,
- OMAP_DSP_MBCMD_FBCTL_ENABLE);
+ mbcompose_send(KFUNC, KFUNC_FBCTL, FBCTL_ENABLE);
}
static int dsp_fbctl_disable(void)
{
+ int ret;
+
+ ret = misc_mbcompose_send_and_wait(KFUNC, KFUNC_FBCTL, FBCTL_DISABLE,
+ NULL);
+ if ((ret < 0) && (ret != -EINTR))
+ printk(KERN_ERR "omapdsp: fb disable error!\n");
+
+ return 0;
+}
+
+static int dsp_fbstat_request(enum fbstat_e st)
+{
+ static DEFINE_MUTEX(fbstat_lock);
int ret = 0;
- struct mbcmd mb;
- if (mutex_lock_interruptible(&ioctl_lock))
- return -ERESTARTSYS;
+ if (mutex_lock_interruptible(&fbstat_lock))
+ return -EINTR;
- ioctl_wait_cmd = MBCMD(KFUNC);
- mbcmd_set(mb, MBCMD(KFUNC), OMAP_DSP_MBCMD_KFUNC_FBCTL,
- OMAP_DSP_MBCMD_FBCTL_DISABLE);
- dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
- if (ioctl_wait_cmd != 0) {
- printk(KERN_ERR "omapdsp: fb disable error!\n");
- ret = -EINVAL;
+ if (st == fbstat)
+ goto up_out;
+
+ switch (st) {
+ case FBSTAT_ENABLED:
+ dsp_fbctl_enable();
+ break;
+ case FBSTAT_DISABLED:
+ if ((ret = dsp_fbctl_disable()) < 0)
+ goto up_out;
+ break;
+ default:
+ BUG();
}
- mutex_unlock(&ioctl_lock);
- return ret;
+ fbstat = st;
+up_out:
+ mutex_unlock(&fbstat_lock);
+ return 0;
}
+#endif /* CONFIG_OMAP_DSP_FBEXPORT */
/*
* DSP control device file operations
/*
* command level 1: commands which don't need lock
*/
- case OMAP_DSP_IOCTL_RUN:
+ case DSPCTL_IOCTL_RUN:
dsp_cpustat_request(CPUSTAT_RUN);
break;
- case OMAP_DSP_IOCTL_RESET:
+ case DSPCTL_IOCTL_RESET:
dsp_cpustat_request(CPUSTAT_RESET);
break;
- case OMAP_DSP_IOCTL_SETRSTVECT:
- ret = dsp_set_rstvect((unsigned long)arg);
+ case DSPCTL_IOCTL_SETRSTVECT:
+ ret = dsp_set_rstvect((dsp_long_t)arg);
break;
- case OMAP_DSP_IOCTL_CPU_IDLE:
+#ifdef CONFIG_ARCH_OMAP1
+ case DSPCTL_IOCTL_CPU_IDLE:
dsp_cpustat_request(CPUSTAT_CPU_IDLE);
break;
- case OMAP_DSP_IOCTL_GBL_IDLE:
+ case DSPCTL_IOCTL_GBL_IDLE:
dsp_cpustat_request(CPUSTAT_GBL_IDLE);
break;
- case OMAP_DSP_IOCTL_MPUI_WORDSWAP_ON:
+ case DSPCTL_IOCTL_MPUI_WORDSWAP_ON:
mpui_wordswap_on();
break;
- case OMAP_DSP_IOCTL_MPUI_WORDSWAP_OFF:
+ case DSPCTL_IOCTL_MPUI_WORDSWAP_OFF:
mpui_wordswap_off();
break;
- case OMAP_DSP_IOCTL_MPUI_BYTESWAP_ON:
+ case DSPCTL_IOCTL_MPUI_BYTESWAP_ON:
mpui_byteswap_on();
break;
- case OMAP_DSP_IOCTL_MPUI_BYTESWAP_OFF:
+ case DSPCTL_IOCTL_MPUI_BYTESWAP_OFF:
mpui_byteswap_off();
break;
+#endif /* CONFIG_ARCH_OMAP1 */
+
+ case DSPCTL_IOCTL_TASKCNT:
+ ret = dsp_task_count();
+ break;
- case OMAP_DSP_IOCTL_MBSEND:
+ case DSPCTL_IOCTL_MBSEND:
{
struct omap_dsp_mailbox_cmd u_cmd;
- struct mbcmd_hw mb;
+ mbx_msg_t msg;
if (copy_from_user(&u_cmd, (void *)arg, sizeof(u_cmd)))
return -EFAULT;
- mb.cmd = u_cmd.cmd;
- mb.data = u_cmd.data;
- ret = dsp_mbcmd_send((struct mbcmd *)&mb);
+ msg = (u_cmd.cmd << 16) | u_cmd.data;
+ ret = dsp_mbcmd_send((struct mbcmd *)&msg);
break;
}
- case OMAP_DSP_IOCTL_SETVAR:
+ case DSPCTL_IOCTL_SETVAR:
{
struct omap_dsp_varinfo var;
if (copy_from_user(&var, (void *)arg, sizeof(var)))
break;
}
- case OMAP_DSP_IOCTL_RUNLEVEL:
- dsp_runlevel(arg);
+ case DSPCTL_IOCTL_RUNLEVEL:
+ ret = dsp_set_runlevel(arg);
break;
- case OMAP_DSP_IOCTL_FBEN:
- dsp_fbctl_enable();
- return 0;
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+ case DSPCTL_IOCTL_FBEN:
+ ret = dsp_fbstat_request(FBSTAT_ENABLED);
+ break;
+#endif
/*
* command level 2: commands which need lock
*/
- case OMAP_DSP_IOCTL_DSPCFG:
- ret = dspcfg();
+ case DSPCTL_IOCTL_DSPCFG:
+ ret = dsp_cfgstat_request(CFGSTAT_READY);
break;
- case OMAP_DSP_IOCTL_DSPUNCFG:
- ret = dspuncfg();
+ case DSPCTL_IOCTL_DSPUNCFG:
+ ret = dsp_cfgstat_request(CFGSTAT_CLEAN);
break;
- case OMAP_DSP_IOCTL_TASKCNT:
- ret = dsp_task_count();
- break;
-
- case OMAP_DSP_IOCTL_POLL:
+ case DSPCTL_IOCTL_POLL:
ret = dsp_poll();
break;
- case OMAP_DSP_IOCTL_FBDIS:
- ret = dsp_fbctl_disable();
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+ case DSPCTL_IOCTL_FBDIS:
+ ret = dsp_fbstat_request(FBSTAT_DISABLED);
break;
+#endif
- /*
- * FIXME: cpu status control for suspend - resume
- */
- case OMAP_DSP_IOCTL_SUSPEND:
- if ((ret = dsp_suspend()) < 0)
+ case DSPCTL_IOCTL_SUSPEND:
+ if ((ret = dsp_cfgstat_request(CFGSTAT_SUSPEND)) < 0)
break;
dsp_cpustat_request(CPUSTAT_RESET);
break;
- case OMAP_DSP_IOCTL_RESUME:
- if ((ret = dsp_resume()) < 0)
+ case DSPCTL_IOCTL_RESUME:
+ if ((ret = dsp_cfgstat_request(CFGSTAT_RESUME)) < 0)
break;
dsp_cpustat_request(CPUSTAT_RUN);
break;
- case OMAP_DSP_IOCTL_REGMEMR:
+ case DSPCTL_IOCTL_REGMEMR:
{
struct omap_dsp_reginfo *u_reg = (void *)arg;
- unsigned short adr, val;
+ u16 adr, val;
- if (copy_from_user(&adr, &u_reg->adr, sizeof(short)))
+ if (copy_from_user(&adr, &u_reg->adr, sizeof(u16)))
return -EFAULT;
- if ((ret = dsp_regread(OMAP_DSP_MBCMD_REGRW_MEMR,
- adr, &val)) < 0)
+ if ((ret = dsp_regread(SPACE_MEM, adr, &val)) < 0)
return ret;
- if (copy_to_user(&u_reg->val, &val, sizeof(short)))
+ if (copy_to_user(&u_reg->val, &val, sizeof(u16)))
return -EFAULT;
break;
}
- case OMAP_DSP_IOCTL_REGMEMW:
+ case DSPCTL_IOCTL_REGMEMW:
{
struct omap_dsp_reginfo reg;
if (copy_from_user(®, (void *)arg, sizeof(reg)))
return -EFAULT;
- ret = dsp_regwrite(OMAP_DSP_MBCMD_REGRW_MEMW,
- reg.adr, reg.val);
+ ret = dsp_regwrite(SPACE_MEM, reg.adr, reg.val);
break;
}
- case OMAP_DSP_IOCTL_REGIOR:
+ case DSPCTL_IOCTL_REGIOR:
{
struct omap_dsp_reginfo *u_reg = (void *)arg;
- unsigned short adr, val;
+ u16 adr, val;
- if (copy_from_user(&adr, &u_reg->adr, sizeof(short)))
+ if (copy_from_user(&adr, &u_reg->adr, sizeof(u16)))
return -EFAULT;
- if ((ret = dsp_regread(OMAP_DSP_MBCMD_REGRW_IOR,
- adr, &val)) < 0)
+ if ((ret = dsp_regread(SPACE_IO, adr, &val)) < 0)
return ret;
- if (copy_to_user(&u_reg->val, &val, sizeof(short)))
+ if (copy_to_user(&u_reg->val, &val, sizeof(u16)))
return -EFAULT;
break;
}
- case OMAP_DSP_IOCTL_REGIOW:
+ case DSPCTL_IOCTL_REGIOW:
{
struct omap_dsp_reginfo reg;
if (copy_from_user(®, (void *)arg, sizeof(reg)))
return -EFAULT;
- ret = dsp_regwrite(OMAP_DSP_MBCMD_REGRW_IOW,
- reg.adr, reg.val);
+ ret = dsp_regwrite(SPACE_IO, reg.adr, reg.val);
break;
}
- case OMAP_DSP_IOCTL_GETVAR:
+ case DSPCTL_IOCTL_GETVAR:
{
struct omap_dsp_varinfo *u_var = (void *)arg;
- unsigned char varid;
- unsigned short val[5]; /* maximum */
+ u8 varid;
+ u16 val[5]; /* maximum */
int argc;
- if (copy_from_user(&varid, &u_var->varid, sizeof(char)))
+ if (copy_from_user(&varid, &u_var->varid, sizeof(u8)))
return -EFAULT;
switch (varid) {
- case OMAP_DSP_MBCMD_VARID_ICRMASK:
+ case VARID_ICRMASK:
argc = 1;
break;
- case OMAP_DSP_MBCMD_VARID_LOADINFO:
+ case VARID_LOADINFO:
argc = 5;
break;
default:
return -EINVAL;
}
- if ((ret = dsp_getvar(varid, val, argc)) < 0)
+ if ((ret = dsp_getvar(varid, val)) < 0)
return ret;
- if (copy_to_user(&u_var->val, val, sizeof(short) * argc))
+ if (copy_to_user(&u_var->val, val, sizeof(u16) * argc))
return -EFAULT;
break;
}
}
/*
- * functions called from mailbox1 interrupt routine
+ * functions called from mailbox interrupt routine
*/
-void mbx1_suspend(struct mbcmd *mb)
+void mbx_suspend(struct mbcmd *mb)
+{
+ misc_mbcmd_response(mb, 0, 0);
+}
+
+void mbx_dspcfg(struct mbcmd *mb)
{
- if (!waitqueue_active(&ioctl_wait_q) ||
- (ioctl_wait_cmd != MBCMD(SUSPEND))) {
+ u8 last = mb->cmd_l & 0x80;
+ u8 cfgcmd = mb->cmd_l & 0x7f;
+ static dsp_long_t tmp_ipb_adr;
+
+ if (!waitqueue_active(&misc_mb_wait.wait_q) ||
+ (misc_mb_wait.cmd_h != MBX_CMD_DSP_DSPCFG)) {
printk(KERN_WARNING
- "mbx: SUSPEND command received, "
+ "mbx: DSPCFG command received, "
"but nobody is waiting for it...\n");
return;
}
- ioctl_wait_cmd = 0;
- wake_up_interruptible(&ioctl_wait_q);
-}
-
-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_adr;
-
/* mailbox protocol check */
- if (cfgcmd == OMAP_DSP_MBCMD_DSPCFG_PROTREV) {
- if (!waitqueue_active(&ioctl_wait_q) ||
- (ioctl_wait_cmd != MBCMD(DSPCFG))) {
- printk(KERN_WARNING
- "mbx: DSPCFG command received, "
- "but nobody is waiting for it...\n");
- return;
- }
-
+ if (cfgcmd == DSPCFG_PROTREV) {
mbx_revision = mb->data;
- if (mbx_revision == OMAP_DSP_MBPROT_REVISION)
+ if (mbx_revision == MBPROT_REVISION)
return;
#ifdef OLD_BINARY_SUPPORT
else if ((mbx_revision == MBREV_3_0) ||
printk(KERN_ERR
"mbx: protocol revision check error!\n"
" expected=0x%04x, received=0x%04x\n",
- OMAP_DSP_MBPROT_REVISION, mb->data);
+ MBPROT_REVISION, mb->data);
mbx_revision = -1;
goto abort1;
}
return;
}
- if (!waitqueue_active(&ioctl_wait_q) ||
- (ioctl_wait_cmd != MBCMD(DSPCFG))) {
- printk(KERN_WARNING
- "mbx: DSPCFG command received, "
- "but nobody is waiting for it...\n");
- return;
- }
-
switch (cfgcmd) {
- case OMAP_DSP_MBCMD_DSPCFG_SYSADRH:
- tmp_ipb_adr = (unsigned long)mb->data << 16;
+ case DSPCFG_SYSADRH:
+ tmp_ipb_adr = (u32)mb->data << 16;
break;
- case OMAP_DSP_MBCMD_DSPCFG_SYSADRL:
+ case DSPCFG_SYSADRL:
tmp_ipb_adr |= mb->data;
break;
- case OMAP_DSP_MBCMD_DSPCFG_ABORT:
+ case DSPCFG_ABORT:
goto abort1;
default:
if (last) {
void *badr;
- unsigned short bln;
- unsigned short bsz;
- volatile unsigned short *buf;
+ u16 bln;
+ u16 bsz;
+ volatile u16 *buf;
void *ipb_sys_da, *ipb_sys_ad;
- void *mbseq;
+ void *mbseq; /* FIXME: 3.4 obsolete */
short *dbg_buf;
- unsigned short dbg_buf_sz, dbg_line_sz;
+ u16 dbg_buf_sz, dbg_line_sz;
struct mem_sync_struct mem_sync, *mem_syncp;
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) {
+ if (dsp_mem_enable(ipbuf_sys_da) < 0) {
+ printk(KERN_ERR "mbx: DSPCFG - ipbuf_sys_da read failed!\n");
+ goto abort1;
+ }
+ if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) {
printk(KERN_ERR "mbx: DSPCFG - IPBUF sync failed!\n");
+ dsp_mem_disable(ipbuf_sys_da);
goto abort1;
}
/*
* we must read with 16bit-access
*/
#ifdef OLD_BINARY_SUPPORT
- if (mbx_revision == OMAP_DSP_MBPROT_REVISION) {
+ if (mbx_revision == MBPROT_REVISION) {
#endif
buf = ipbuf_sys_da->d;
n_stask = buf[0];
dbg_buf_sz = 0;
dbg_line_sz = 0;
mem_syncp = NULL;
- } else /* should not occur */
+ } else { /* should not occur */
+ dsp_mem_disable(ipbuf_sys_da);
goto abort1;
+ }
#endif /* OLD_BINARY_SUPPORT */
release_ipbuf_pvt(ipbuf_sys_da);
+ dsp_mem_disable(ipbuf_sys_da);
/*
* following configurations need to be done before
goto abort1;
if (ipbuf_config(bln, bsz, badr) < 0)
goto abort1;
- if (dsp_mb_config(mbseq) < 0)
+ if (dsp_mbx_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);
+ misc_mb_wait.cmd_h = 0;
+ wake_up_interruptible(&misc_mb_wait.wait_q);
}
return;
abort2:
ipbuf_stop();
abort1:
- wake_up_interruptible(&ioctl_wait_q);
+ wake_up_interruptible(&misc_mb_wait.wait_q);
return;
}
-void mbx1_poll(struct mbcmd *mb)
+void mbx_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);
+ misc_mbcmd_response(mb, 0, 0);
}
-void mbx1_regrw(struct mbcmd *mb)
+void mbx_regrw(struct mbcmd *mb)
{
- if (!waitqueue_active(&ioctl_wait_q) ||
- (ioctl_wait_cmd != MBCMD(REGRW))) {
- printk(KERN_WARNING
- "mbx: REGRW command received, "
- "but nobody is waiting for it...\n");
- return;
- }
-
switch (mb->cmd_l) {
- case OMAP_DSP_MBCMD_REGRW_DATA:
- ioctl_wait_cmd = 0;
- varread_val[0] = mb->data;
- wake_up_interruptible(&ioctl_wait_q);
- return;
-
+ case REGRW_DATA:
+ misc_mbcmd_response(mb, 1, 0);
+ break;
default:
printk(KERN_ERR
"mbx: Illegal REGRW command: "
}
}
-void mbx1_getvar(struct mbcmd *mb)
+void mbx_getvar(struct mbcmd *mb)
{
- unsigned char varid = mb->cmd_l;
- int i;
- volatile unsigned short *buf;
-
- if (!waitqueue_active(&ioctl_wait_q) ||
- (ioctl_wait_cmd != MBCMD(GETVAR))) {
- printk(KERN_WARNING
- "mbx: GETVAR command received, "
- "but nobody is waiting for it...\n");
- return;
- }
-
- ioctl_wait_cmd = 0;
- switch (varid) {
- case OMAP_DSP_MBCMD_VARID_ICRMASK:
- varread_val[0] = mb->data;
+ switch (mb->cmd_l) {
+ case VARID_ICRMASK:
+ misc_mbcmd_response(mb, 1, 1);
break;
- case OMAP_DSP_MBCMD_VARID_LOADINFO:
- {
- if (sync_with_dsp(&ipbuf_sys_da->s, OMAP_DSP_TID_ANON, 10) < 0) {
- printk(KERN_ERR
- "mbx: GETVAR - IPBUF sync failed!\n");
- return;
- }
- /* need word access. do not use memcpy. */
- buf = ipbuf_sys_da->d;
- for (i = 0; i < 5; i++) {
- varread_val[i] = buf[i];
- }
- release_ipbuf_pvt(ipbuf_sys_da);
- break;
- }
+ case VARID_LOADINFO:
+ misc_mbcmd_response(mb, 5, 1);
+ break;
+ default:
+ printk(KERN_ERR
+ "mbx: Illegal GETVAR command: "
+ "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data);
+ return;
}
- wake_up_interruptible(&ioctl_wait_q);
+}
- return;
+void mbx_fbctl_disable(struct mbcmd *mb)
+{
+ misc_mbcmd_response(mb, 0, 0);
}
+struct file_operations dsp_ctl_fops = {
+ .owner = THIS_MODULE,
+ .ioctl = dsp_ctl_ioctl,
+};
+
/*
* sysfs files
*/
+
+/* ifver */
static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
* 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
+ * DSPCTL_IOCTL_GBL_IDLE
+ * DSPCTL_IOCTL_CPU_IDLE (instead of DSPCTL_IOCTL_IDLE)
+ * DSPCTL_IOCTL_POLL
*/
/*
return len;
}
-static struct device_attribute dev_attr_ifver = __ATTR_RO(ifver);
+/* cpustat */
+static char *cpustat_name[CPUSTAT_MAX] = {
+ [CPUSTAT_RESET] = "reset",
+#ifdef CONFIG_ARCH_OMAP1
+ [CPUSTAT_GBL_IDLE] = "gbl_idle",
+ [CPUSTAT_CPU_IDLE] = "cpu_idle",
+#endif
+ [CPUSTAT_RUN] = "run",
+};
static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
- return sprintf(buf, "%s\n", cpustat_name(dsp_cpustat_get_stat()));
+ return sprintf(buf, "%s\n", cpustat_name[dsp_cpustat_get_stat()]);
}
-static struct device_attribute dev_attr_cpustat = __ATTR_RO(cpustat);
-
+/* icrmask */
static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- unsigned short mask;
+ u16 mask;
int ret;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
mask = simple_strtol(buf, NULL, 16);
dsp_cpustat_set_icrmask(mask);
- if (dsp_is_ready()) {
- ret = dsp_setvar(OMAP_DSP_MBCMD_VARID_ICRMASK, mask);
+ if (dsp_cfgstat_get_stat() == CFGSTAT_READY) {
+ ret = dsp_setvar(VARID_ICRMASK, mask);
if (ret < 0)
return ret;
}
- return strlen(buf);
+ return count;
}
-static struct device_attribute dev_attr_icrmask =
- __ATTR(icrmask, S_IWUSR | S_IRUGO, icrmask_show, icrmask_store);
-
+/* loadinfo */
static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int len;
int ret;
- static unsigned short val[5];
+ u16 val[5];
- if ((ret = dsp_getvar(OMAP_DSP_MBCMD_VARID_LOADINFO, val, 5)) < 0)
+ if ((ret = dsp_getvar(VARID_LOADINFO, val)) < 0)
return ret;
- /* load info value range is 0(free) - 10000(busy) */
+ /*
+ * load info value range is 0(free) - 10000(busy):
+ * if CPU load is not measured on DSP, it sets 0xffff at val[0].
+ */
+
+ if (val[0] == 0xffff) {
+ len = sprintf(buf,
+ "currently DSP load info is not available.\n");
+ goto out;
+ }
+
len = sprintf(buf,
"DSP load info:\n"
" 10ms average = %3d.%02d%%\n"
val[0]/100, val[0]%100,
val[1]/100, val[1]%100, val[2]/100, val[2]%100,
val[3]/100, val[3]%100, val[4]/100, val[4]%100);
+out:
return len;
}
-/*
- * This is declared at the top of this file.
- *
- * static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
- */
-
-void mbx1_fbctl_disable(void)
-{
- if (!waitqueue_active(&ioctl_wait_q) ||
- (ioctl_wait_cmd != MBCMD(KFUNC))) {
- printk(KERN_WARNING
- "mbx: KFUNC:FBCTL command received, "
- "but nobody is waiting for it...\n");
- return;
- }
- ioctl_wait_cmd = 0;
- wake_up_interruptible(&ioctl_wait_q);
-}
-
-#ifdef CONFIG_PROC_FS
-/* for backward compatibility */
-static int version_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- /*
- * This entry is read by 3.1 tools only, so leave it as is.
- * 3.2 and later will read from sysfs file.
- */
- return sprintf(page, "3.1\n");
-}
-
-static void __init dsp_ctl_create_proc(void)
-{
- struct proc_dir_entry *ent;
-
- /* version */
- ent = create_proc_read_entry("version", 0, procdir_dsp,
- version_read_proc, NULL);
- if (ent == NULL) {
- printk(KERN_ERR
- "omapdsp: failed to register proc device: version\n");
- }
-}
-
-static void dsp_ctl_remove_proc(void)
-{
- remove_proc_entry("version", procdir_dsp);
-}
-#endif /* CONFIG_PROC_FS */
-
-struct file_operations dsp_ctl_fops = {
- .owner = THIS_MODULE,
- .ioctl = dsp_ctl_ioctl,
-};
-
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();
-#endif
}
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();
-#endif
}
/*
- * linux/arch/arm/mach-omap/dsp/dsp_ctl_core.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * OMAP DSP control devices core driver
+ * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2004,2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/07/26: DSP Gateway version 3.3
*/
-#include <linux/module.h>
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/init.h>
-#include <asm/arch/dsp.h>
-#include "hardware_dsp.h"
+#include "dsp.h"
#define CTL_MINOR 0
#define MEM_MINOR 1
{
int retval;
int i;
- struct class_device *cdev;
retval = register_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl",
&dsp_ctl_core_fops);
dsp_ctl_class = class_create(THIS_MODULE, "dspctl");
for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
- cdev = class_device_create(dsp_ctl_class, NULL,
+ class_device_create(dsp_ctl_class, NULL,
MKDEV(OMAP_DSP_CTL_MAJOR,
dev_list[i].minor),
NULL, dev_list[i].devname);
--- /dev/null
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+/*
+ * DSP mailbox protocol definitions
+ */
+#define MBPROT_REVISION 0x0019
+
+#define TCTL_TINIT 0x0000
+#define TCTL_TEN 0x0001
+#define TCTL_TDIS 0x0002
+#define TCTL_TCLR 0x0003
+#define TCTL_TCLR_FORCE 0x0004
+
+#define RUNLEVEL_USER 0x01
+#define RUNLEVEL_SUPER 0x0e
+#define RUNLEVEL_RECOVERY 0x10
+
+#define PM_DISABLE 0x00
+#define PM_ENABLE 0x01
+
+#define KFUNC_FBCTL 0x00
+#define KFUNC_AUDIO_PWR 0x01
+
+#define FBCTL_UPD 0x0000
+#define FBCTL_ENABLE 0x0002
+#define FBCTL_DISABLE 0x0003
+
+#define AUDIO_PWR_UP 0x0000
+#define AUDIO_PWR_DOWN1 0x0001
+#define AUDIO_PWR_DOWN2 0x0002
+
+#define TDEL_SAFE 0x0000
+#define TDEL_KILL 0x0001
+
+#define DSPCFG_REQ 0x00
+#define DSPCFG_SYSADRH 0x28
+#define DSPCFG_SYSADRL 0x29
+#define DSPCFG_PROTREV 0x70
+#define DSPCFG_ABORT 0x78
+#define DSPCFG_LAST 0x80
+
+#define REGRW_MEMR 0x00
+#define REGRW_MEMW 0x01
+#define REGRW_IOR 0x02
+#define REGRW_IOW 0x03
+#define REGRW_DATA 0x04
+
+#define VARID_ICRMASK 0x00
+#define VARID_LOADINFO 0x01
+
+#define TTYP_ARCV 0x0001
+#define TTYP_ASND 0x0002
+#define TTYP_BKMD 0x0004
+#define TTYP_BKDM 0x0008
+#define TTYP_PVMD 0x0010
+#define TTYP_PVDM 0x0020
+
+#define EID_BADTID 0x10
+#define EID_BADTCN 0x11
+#define EID_BADBID 0x20
+#define EID_BADCNT 0x21
+#define EID_NOTLOCKED 0x22
+#define EID_STVBUF 0x23
+#define EID_BADADR 0x24
+#define EID_BADTCTL 0x30
+#define EID_BADPARAM 0x50
+#define EID_FATAL 0x58
+#define EID_NOMEM 0xc0
+#define EID_NORES 0xc1
+#define EID_IPBFULL 0xc2
+#define EID_WDT 0xd0
+#define EID_TASKNOTRDY 0xe0
+#define EID_TASKBSY 0xe1
+#define EID_TASKERR 0xef
+#define EID_BADCFGTYP 0xf0
+#define EID_DEBUG 0xf8
+#define EID_BADSEQ 0xfe
+#define EID_BADCMD 0xff
+
+#define TNM_LEN 16
+
+#define TID_FREE 0xff
+#define TID_ANON 0xfe
+
+#define BID_NULL 0xffff
+#define BID_PVT 0xfffe
/*
- * linux/arch/arm/mach-omap/dsp/dsp_mem.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * OMAP DSP memory driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
- *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
* Conversion to mempool API and ARM MMU section mapping
* by Paul Mundt <paul.mundt@nokia.com>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- * 2005/06/09: DSP Gateway version 3.3
*/
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/major.h>
#include <linux/fs.h>
-#include <linux/bootmem.h>
#include <linux/fb.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/ioctls.h>
#include <asm/irq.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/arch/tc.h>
#include <asm/arch/omapfb.h>
-#include <asm/arch/dsp.h>
+#include <asm/arch/mailbox.h>
#include <asm/arch/dsp_common.h>
#include "uaccess_dsp.h"
-#include "ipbuf.h"
+#include "dsp_mbcmd.h"
+#include "../mailbox_hw.h"
#include "dsp.h"
+#include "ioctl.h"
+
+#ifdef CONFIG_ARCH_OMAP2
+#define IOMAP_VAL 0x3f
+#endif
-#define SZ_1MB 0x100000
-#define SZ_64KB 0x10000
-#define SZ_4KB 0x1000
#define SZ_1KB 0x400
+#define SZ_4KB 0x1000
+#define SZ_64KB 0x10000
+#define SZ_1MB 0x100000
+#define SZ_16MB 0x1000000
#define is_aligned(adr,align) (!((adr)&((align)-1)))
-#define ORDER_1MB (20 - PAGE_SHIFT)
-#define ORDER_64KB (16 - PAGE_SHIFT)
#define ORDER_4KB (12 - PAGE_SHIFT)
+#define ORDER_64KB (16 - PAGE_SHIFT)
+#define ORDER_1MB (20 - PAGE_SHIFT)
+
+/*
+ * absorb DSP MMU register size and location difference
+ */
+#if defined(CONFIG_ARCH_OMAP1)
+typedef u16 dsp_mmu_reg_t;
+#define dsp_mmu_read_reg(a) omap_readw(a)
+#define dsp_mmu_write_reg(v,a) omap_writew(v,a)
+#elif defined(CONFIG_ARCH_OMAP2)
+typedef u32 dsp_mmu_reg_t;
+#define dsp_mmu_read_reg(a) readl(a)
+#define dsp_mmu_write_reg(v,a) writel(v,a)
+#define dsp_ipi_read_reg(a) readl(a)
+#define dsp_ipi_write_reg(v,a) writel(v,a)
+#endif
-#define PGDIR_MASK (~(PGDIR_SIZE-1))
-#define PGDIR_ALIGN(addr) (((addr)+PGDIR_SIZE-1)&(PGDIR_MASK))
+#if defined(CONFIG_ARCH_OMAP1)
#define dsp_mmu_enable() \
do { \
- omap_writew(DSPMMU_CNTL_MMU_EN | DSPMMU_CNTL_RESET_SW, \
- DSPMMU_CNTL); \
+ dsp_mmu_write_reg(DSP_MMU_CNTL_MMU_EN | DSP_MMU_CNTL_RESET_SW, \
+ DSP_MMU_CNTL); \
} while(0)
#define dsp_mmu_disable() \
- do { omap_writew(0, DSPMMU_CNTL); } while(0)
+ do { \
+ dsp_mmu_write_reg(0, DSP_MMU_CNTL); \
+ } while(0)
+#define __dsp_mmu_itack() \
+ do { \
+ dsp_mmu_write_reg(DSP_MMU_IT_ACK_IT_ACK, DSP_MMU_IT_ACK); \
+ } while(0)
+
+#elif defined(CONFIG_ARCH_OMAP2)
+
+#define dsp_mmu_enable() \
+ do { \
+ dsp_mmu_write_reg(DSP_MMU_CNTL_MMUENABLE, DSP_MMU_CNTL); \
+ } while(0)
+#define dsp_mmu_disable() \
+ do { \
+ dsp_mmu_write_reg(0, DSP_MMU_CNTL); \
+ } while(0)
+#define dsp_mmu_reset() \
+ do { \
+ dsp_mmu_write_reg(dsp_mmu_read_reg(DSP_MMU_SYSCONFIG) | \
+ DSP_MMU_SYSCONFIG_SOFTRESET, \
+ DSP_MMU_SYSCONFIG); \
+ } while(0)
+
+#endif /* CONFIG_ARCH_OMAP2 */
+
#define dsp_mmu_flush() \
do { \
- omap_writew(DSPMMU_FLUSH_ENTRY_FLUSH_ENTRY, \
- DSPMMU_FLUSH_ENTRY); \
+ dsp_mmu_write_reg(DSP_MMU_FLUSH_ENTRY_FLUSH_ENTRY, \
+ DSP_MMU_FLUSH_ENTRY); \
} while(0)
#define __dsp_mmu_gflush() \
- do { omap_writew(DSPMMU_GFLUSH_GFLUSH, DSPMMU_GFLUSH); } while(0)
-#define __dsp_mmu_itack() \
- do { omap_writew(DSPMMU_IT_ACK_IT_ACK, DSPMMU_IT_ACK); } while(0)
+ do { \
+ dsp_mmu_write_reg(DSP_MMU_GFLUSH_GFLUSH, DSP_MMU_GFLUSH); \
+ } while(0)
+/*
+ * absorb register name difference
+ */
+#ifdef CONFIG_ARCH_OMAP1
+#define DSP_MMU_CAM_P DSP_MMU_CAM_L_P
+#define DSP_MMU_CAM_V DSP_MMU_CAM_L_V
+#define DSP_MMU_CAM_PAGESIZE_MASK DSP_MMU_CAM_L_PAGESIZE_MASK
+#define DSP_MMU_CAM_PAGESIZE_1MB DSP_MMU_CAM_L_PAGESIZE_1MB
+#define DSP_MMU_CAM_PAGESIZE_64KB DSP_MMU_CAM_L_PAGESIZE_64KB
+#define DSP_MMU_CAM_PAGESIZE_4KB DSP_MMU_CAM_L_PAGESIZE_4KB
+#define DSP_MMU_CAM_PAGESIZE_1KB DSP_MMU_CAM_L_PAGESIZE_1KB
+#endif /* CONFIG_ARCH_OMAP1 */
+
+/*
+ * OMAP1 EMIFF access
+ */
+#ifdef CONFIG_ARCH_OMAP1
#define EMIF_PRIO_LB_MASK 0x0000f000
#define EMIF_PRIO_LB_SHIFT 12
#define EMIF_PRIO_DMA_MASK 0x00000f00
#define set_emiff_dma_prio(prio) \
do { \
omap_writel((omap_readl(OMAP_TC_OCPT1_PRIOR) & \
- ~EMIF_PRIO_DMA_MASK) | \
+ ~EMIF_PRIO_DMA_MASK) | \
((prio) << EMIF_PRIO_DMA_SHIFT), \
OMAP_TC_OCPT1_PRIOR); \
} while(0)
+#endif /* CONFIG_ARCH_OMAP1 */
-enum exmap_type {
+enum exmap_type_e {
EXMAP_TYPE_MEM,
EXMAP_TYPE_FB
};
-struct exmap_tbl {
+struct exmap_tbl_entry {
unsigned int valid:1;
- unsigned int cntnu:1; /* grouping */
+ unsigned int prsvd:1; /* preserved */
int usecount; /* reference count by mmap */
- enum exmap_type type;
+ enum exmap_type_e type;
void *buf; /* virtual address of the buffer,
* i.e. 0xc0000000 - */
void *vadr; /* DSP shadow space,
* i.e. 0xe0000000 - 0xe0ffffff */
unsigned int order;
+ struct {
+ int prev;
+ int next;
+ } link; /* grouping */
};
-#define DSPMMU_TLB_LINES 32
-static struct exmap_tbl exmap_tbl[DSPMMU_TLB_LINES];
+
+#define INIT_EXMAP_TBL_ENTRY(ent,b,v,typ,od) \
+ do {\
+ (ent)->buf = (b); \
+ (ent)->vadr = (v); \
+ (ent)->valid = 1; \
+ (ent)->prsvd = 0; \
+ (ent)->usecount = 0; \
+ (ent)->type = (typ); \
+ (ent)->order = (od); \
+ (ent)->link.next = -1; \
+ (ent)->link.prev = -1; \
+ } while (0)
+
+#define INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(ent,b,v) \
+ do {\
+ (ent)->buf = (b); \
+ (ent)->vadr = (v); \
+ (ent)->valid = 1; \
+ (ent)->prsvd = 1; \
+ (ent)->usecount = 0; \
+ (ent)->type = EXMAP_TYPE_MEM; \
+ (ent)->order = 0; \
+ (ent)->link.next = -1; \
+ (ent)->link.prev = -1; \
+ } while (0)
+
+#define DSP_MMU_TLB_LINES 32
+static struct exmap_tbl_entry exmap_tbl[DSP_MMU_TLB_LINES];
+static int exmap_preserved_cnt;
static DECLARE_RWSEM(exmap_sem);
#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
static int omapfb_ready;
#endif
-static int dsp_exunmap(unsigned long dspadr);
+struct cam_ram_regset {
+#if defined(CONFIG_ARCH_OMAP1)
+ dsp_mmu_reg_t cam_h;
+ dsp_mmu_reg_t cam_l;
+ dsp_mmu_reg_t ram_h;
+ dsp_mmu_reg_t ram_l;
+#elif defined(CONFIG_ARCH_OMAP2)
+ dsp_mmu_reg_t cam;
+ dsp_mmu_reg_t ram;
+#endif
+};
+
+struct tlb_entry {
+ dsp_long_t va;
+ unsigned long pa;
+ dsp_mmu_reg_t pgsz, prsvd, valid;
+#if defined(CONFIG_ARCH_OMAP1)
+ dsp_mmu_reg_t ap;
+#elif defined(CONFIG_ARCH_OMAP2)
+ dsp_mmu_reg_t endian, elsz, mixed;
+#endif
+};
+
+#if defined(CONFIG_ARCH_OMAP1)
+#define INIT_TLB_ENTRY(ent,v,p,ps) \
+ do { \
+ (ent)->va = (v); \
+ (ent)->pa = (p); \
+ (ent)->pgsz = (ps); \
+ (ent)->prsvd = 0; \
+ (ent)->ap = DSP_MMU_RAM_L_AP_FA; \
+ } while (0)
+#define INIT_TLB_ENTRY_4KB_PRESERVED(ent,v,p) \
+ do { \
+ (ent)->va = (v); \
+ (ent)->pa = (p); \
+ (ent)->pgsz = DSP_MMU_CAM_PAGESIZE_4KB; \
+ (ent)->prsvd = DSP_MMU_CAM_P; \
+ (ent)->ap = DSP_MMU_RAM_L_AP_FA; \
+ } while (0)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define INIT_TLB_ENTRY(ent,v,p,ps) \
+ do { \
+ (ent)->va = (v); \
+ (ent)->pa = (p); \
+ (ent)->pgsz = (ps); \
+ (ent)->prsvd = 0; \
+ (ent)->endian = DSP_MMU_RAM_ENDIANNESS_LITTLE; \
+ (ent)->elsz = DSP_MMU_RAM_ELEMENTSIZE_16; \
+ (ent)->mixed = 0; \
+ } while (0)
+#define INIT_TLB_ENTRY_4KB_PRESERVED(ent,v,p) \
+ do { \
+ (ent)->va = (v); \
+ (ent)->pa = (p); \
+ (ent)->pgsz = DSP_MMU_CAM_PAGESIZE_4KB; \
+ (ent)->prsvd = DSP_MMU_CAM_P; \
+ (ent)->endian = DSP_MMU_RAM_ENDIANNESS_LITTLE; \
+ (ent)->elsz = DSP_MMU_RAM_ELEMENTSIZE_16; \
+ (ent)->mixed = 0; \
+ } while (0)
+#define INIT_TLB_ENTRY_4KB_ES32_PRESERVED(ent,v,p) \
+ do { \
+ (ent)->va = (v); \
+ (ent)->pa = (p); \
+ (ent)->pgsz = DSP_MMU_CAM_PAGESIZE_4KB; \
+ (ent)->prsvd = DSP_MMU_CAM_P; \
+ (ent)->endian = DSP_MMU_RAM_ENDIANNESS_LITTLE; \
+ (ent)->elsz = DSP_MMU_RAM_ELEMENTSIZE_32; \
+ (ent)->mixed = 0; \
+ } while (0)
+#endif
+
+#if defined(CONFIG_ARCH_OMAP1)
+#define cam_ram_valid(cr) ((cr).cam_l & DSP_MMU_CAM_V)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define cam_ram_valid(cr) ((cr).cam & DSP_MMU_CAM_V)
+#endif
+
+struct tlb_lock {
+ int base;
+ int victim;
+};
+
+static int dsp_exunmap(dsp_long_t dspadr);
static void *dspvect_page;
-static unsigned long dsp_fault_adr;
+static u32 dsp_fault_adr;
static struct mem_sync_struct mem_sync;
-static void *mempool_alloc_from_pool(mempool_t *pool,
- unsigned int __nocast gfp_mask)
+static ssize_t mmu_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static ssize_t mempool_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+
+static struct device_attribute dev_attr_mmu = __ATTR_RO(mmu);
+static struct device_attribute dev_attr_exmap = __ATTR_RO(exmap);
+static struct device_attribute dev_attr_mempool = __ATTR_RO(mempool);
+
+/*
+ * special mempool function:
+ * hope this goes to mm/mempool.c
+ */
+static void *mempool_alloc_from_pool(mempool_t *pool, gfp_t gfp_mask)
{
- spin_lock_irq(&pool->lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->lock, flags);
if (likely(pool->curr_nr)) {
void *element = pool->elements[--pool->curr_nr];
- spin_unlock_irq(&pool->lock);
+ spin_unlock_irqrestore(&pool->lock, flags);
return element;
}
+ spin_unlock_irqrestore(&pool->lock, flags);
- spin_unlock_irq(&pool->lock);
return mempool_alloc(pool, gfp_mask);
}
"omapdsp: size(0x%lx) is not multiple of 64KB.\n", size);
return -EINVAL;
}
+
if (size > DSPSPACE_SIZE) {
printk(KERN_ERR
"omapdsp: size(0x%lx) is larger than DSP memory space "
for (page = ps; page < pe; page++)
ClearPageReserved(page);
- if (buf) {
- if ((order == ORDER_64KB) && likely(kmem_pool_64K))
- mempool_free((void *)buf, kmem_pool_64K);
- else if ((order == ORDER_1MB) && likely(kmem_pool_1M))
- mempool_free((void *)buf, kmem_pool_1M);
- else
- free_pages(buf, order);
- }
+ if ((order == ORDER_64KB) && likely(kmem_pool_64K))
+ mempool_free((void *)buf, kmem_pool_64K);
+ else if ((order == ORDER_1MB) && likely(kmem_pool_1M))
+ mempool_free((void *)buf, kmem_pool_1M);
+ else
+ free_pages(buf, order);
}
static inline void
set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
}
+#if 0
static inline int
exmap_alloc_sect(unsigned long virt, unsigned long phys, int prot)
{
return 0;
}
+#endif
/*
* ARM MMU operations
return 0;
}
+ /* XXX: T.Kobayashi
+ * A process can have old mappings. if we want to clear a pmd,
+ * we need to do it for all proceeses that use the old mapping.
+ */
+#if 0
static inline void
exmap_clear_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end)
{
exmap_clear_pmd_range(pud, addr, next);
} while (pud++, addr = next, addr != end);
}
+#endif
static void exmap_clear_armmmu(unsigned long virt, unsigned long size)
{
+#if 0
unsigned long next, end;
pgd_t *pgd;
printk(KERN_DEBUG
- "omapdsp: unmapping in ARM MMU, v=0x%08lx, sz=0x%lx\n",
+ "omapdsp: unmapping in ARM MMU, v=%#010lx, sz=%#lx\n",
virt, size);
pgd = pgd_offset_k(virt);
exmap_clear_pud_range(pgd, virt, next);
} while (pgd++, virt = next, virt != end);
+#else
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ printk(KERN_DEBUG
+ "omapdsp: unmapping in ARM MMU, v=%#010lx, sz=%#lx\n",
+ virt, size);
+
+ while (size >= PAGE_SIZE) {
+ pgd = pgd_offset_k(virt);
+ pud = pud_offset(pgd, virt);
+ pmd = pmd_offset(pud, virt);
+ pte = pte_offset_kernel(pmd, virt);
+
+ pte_clear(&init_mm, virt, pte);
+ size -= PAGE_SIZE;
+ virt += PAGE_SIZE;
+ }
+
+ BUG_ON(size);
+#endif
}
static int exmap_valid(void *vadr, size_t len)
int i;
start:
- for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+ for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
void *mapadr;
unsigned long mapsize;
- struct exmap_tbl *ent = &exmap_tbl[i];
+ struct exmap_tbl_entry *ent = &exmap_tbl[i];
if (!ent->valid)
continue;
int i;
down_write(&exmap_sem);
- for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+ for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
void *mapadr;
unsigned long mapsize;
- struct exmap_tbl *ent = &exmap_tbl[i];
+ struct exmap_tbl_entry *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)) {
+ if ((vadr + len > mapadr) && (vadr < mapadr + mapsize))
ent->usecount++;
- }
}
up_write(&exmap_sem);
}
int i;
down_write(&exmap_sem);
- for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+ for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
void *mapadr;
unsigned long mapsize;
- struct exmap_tbl *ent = &exmap_tbl[i];
+ struct exmap_tbl_entry *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)) {
+ if ((vadr + len > mapadr) && (vadr < mapadr + mapsize))
ent->usecount--;
- }
}
up_write(&exmap_sem);
}
}
/* EXRAM */
- for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+ for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
void *mapadr;
unsigned long mapsize;
- struct exmap_tbl *ent = &exmap_tbl[i];
+ struct exmap_tbl_entry *ent = &exmap_tbl[i];
if (!ent->valid)
continue;
/*
* DSP MMU operations
*/
-static __inline__ unsigned short get_cam_l_va_mask(unsigned short slst)
-{
- switch (slst) {
- case DSPMMU_CAM_L_SLST_1MB:
- return DSPMMU_CAM_L_VA_TAG_L1_MASK |
- DSPMMU_CAM_L_VA_TAG_L2_MASK_1MB;
- case DSPMMU_CAM_L_SLST_64KB:
- return DSPMMU_CAM_L_VA_TAG_L1_MASK |
- DSPMMU_CAM_L_VA_TAG_L2_MASK_64KB;
- case DSPMMU_CAM_L_SLST_4KB:
- return DSPMMU_CAM_L_VA_TAG_L1_MASK |
- DSPMMU_CAM_L_VA_TAG_L2_MASK_4KB;
- case DSPMMU_CAM_L_SLST_1KB:
- return DSPMMU_CAM_L_VA_TAG_L1_MASK |
- DSPMMU_CAM_L_VA_TAG_L2_MASK_1KB;
+#ifdef CONFIG_ARCH_OMAP1
+static dsp_mmu_reg_t get_cam_l_va_mask(dsp_mmu_reg_t pgsz)
+{
+ switch (pgsz) {
+ case DSP_MMU_CAM_PAGESIZE_1MB:
+ return DSP_MMU_CAM_L_VA_TAG_L1_MASK |
+ DSP_MMU_CAM_L_VA_TAG_L2_MASK_1MB;
+ case DSP_MMU_CAM_PAGESIZE_64KB:
+ return DSP_MMU_CAM_L_VA_TAG_L1_MASK |
+ DSP_MMU_CAM_L_VA_TAG_L2_MASK_64KB;
+ case DSP_MMU_CAM_PAGESIZE_4KB:
+ return DSP_MMU_CAM_L_VA_TAG_L1_MASK |
+ DSP_MMU_CAM_L_VA_TAG_L2_MASK_4KB;
+ case DSP_MMU_CAM_PAGESIZE_1KB:
+ return DSP_MMU_CAM_L_VA_TAG_L1_MASK |
+ DSP_MMU_CAM_L_VA_TAG_L2_MASK_1KB;
}
return 0;
}
+#endif /* CONFIG_ARCH_OMAP1 */
+
+#if defined(CONFIG_ARCH_OMAP1)
+#define get_cam_va_mask(pgsz) \
+ ((u32)DSP_MMU_CAM_H_VA_TAG_H_MASK << 22 | \
+ (u32)get_cam_l_va_mask(pgsz) << 6)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define get_cam_va_mask(pgsz) \
+ ((pgsz == DSP_MMU_CAM_PAGESIZE_16MB) ? 0xff000000 : \
+ (pgsz == DSP_MMU_CAM_PAGESIZE_1MB) ? 0xfff00000 : \
+ (pgsz == DSP_MMU_CAM_PAGESIZE_64KB) ? 0xffff0000 : \
+ (pgsz == DSP_MMU_CAM_PAGESIZE_4KB) ? 0xfffff000 : 0)
+#endif /* CONFIG_ARCH_OMAP2 */
-static __inline__ void get_tlb_lock(int *base, int *victim)
+static void get_tlb_lock(struct tlb_lock *tlb_lock)
{
- unsigned short lock = omap_readw(DSPMMU_LOCK);
- if (base != NULL)
- *base = (lock & DSPMMU_LOCK_BASE_MASK)
- >> DSPMMU_LOCK_BASE_SHIFT;
- if (victim != NULL)
- *victim = (lock & DSPMMU_LOCK_VICTIM_MASK)
- >> DSPMMU_LOCK_VICTIM_SHIFT;
+ dsp_mmu_reg_t lock = dsp_mmu_read_reg(DSP_MMU_LOCK);
+
+ tlb_lock->base = (lock & DSP_MMU_LOCK_BASE_MASK) >>
+ DSP_MMU_LOCK_BASE_SHIFT;
+ tlb_lock->victim = (lock & DSP_MMU_LOCK_VICTIM_MASK) >>
+ DSP_MMU_LOCK_VICTIM_SHIFT;
}
-static __inline__ void set_tlb_lock(int base, int victim)
+static void set_tlb_lock(struct tlb_lock *tlb_lock)
{
- omap_writew((base << DSPMMU_LOCK_BASE_SHIFT) |
- (victim << DSPMMU_LOCK_VICTIM_SHIFT), DSPMMU_LOCK);
+ dsp_mmu_write_reg((tlb_lock->base << DSP_MMU_LOCK_BASE_SHIFT) |
+ (tlb_lock->victim << DSP_MMU_LOCK_VICTIM_SHIFT),
+ DSP_MMU_LOCK);
}
-static __inline__ void __read_tlb(unsigned short lbase, unsigned short victim,
- unsigned short *cam_h, unsigned short *cam_l,
- unsigned short *ram_h, unsigned short *ram_l)
+static void __read_tlb(struct tlb_lock *tlb_lock, struct cam_ram_regset *cr)
{
/* set victim */
- set_tlb_lock(lbase, victim);
+ set_tlb_lock(tlb_lock);
+#if defined(CONFIG_ARCH_OMAP1)
/* read a TLB entry */
- omap_writew(DSPMMU_LD_TLB_RD, DSPMMU_LD_TLB);
-
- if (cam_h != NULL)
- *cam_h = omap_readw(DSPMMU_READ_CAM_H);
- if (cam_l != NULL)
- *cam_l = omap_readw(DSPMMU_READ_CAM_L);
- if (ram_h != NULL)
- *ram_h = omap_readw(DSPMMU_READ_RAM_H);
- if (ram_l != NULL)
- *ram_l = omap_readw(DSPMMU_READ_RAM_L);
+ dsp_mmu_write_reg(DSP_MMU_LD_TLB_RD, DSP_MMU_LD_TLB);
+
+ cr->cam_h = dsp_mmu_read_reg(DSP_MMU_READ_CAM_H);
+ cr->cam_l = dsp_mmu_read_reg(DSP_MMU_READ_CAM_L);
+ cr->ram_h = dsp_mmu_read_reg(DSP_MMU_READ_RAM_H);
+ cr->ram_l = dsp_mmu_read_reg(DSP_MMU_READ_RAM_L);
+#elif defined(CONFIG_ARCH_OMAP2)
+ cr->cam = dsp_mmu_read_reg(DSP_MMU_READ_CAM);
+ cr->ram = dsp_mmu_read_reg(DSP_MMU_READ_RAM);
+#endif
}
-static __inline__ void __load_tlb(unsigned short cam_h, unsigned short cam_l,
- unsigned short ram_h, unsigned short ram_l)
+static void __load_tlb(struct cam_ram_regset *cr)
{
- omap_writew(cam_h, DSPMMU_CAM_H);
- omap_writew(cam_l, DSPMMU_CAM_L);
- omap_writew(ram_h, DSPMMU_RAM_H);
- omap_writew(ram_l, DSPMMU_RAM_L);
+#if defined(CONFIG_ARCH_OMAP1)
+ dsp_mmu_write_reg(cr->cam_h, DSP_MMU_CAM_H);
+ dsp_mmu_write_reg(cr->cam_l, DSP_MMU_CAM_L);
+ dsp_mmu_write_reg(cr->ram_h, DSP_MMU_RAM_H);
+ dsp_mmu_write_reg(cr->ram_l, DSP_MMU_RAM_L);
+#elif defined(CONFIG_ARCH_OMAP2)
+ dsp_mmu_write_reg(cr->cam | DSP_MMU_CAM_V, DSP_MMU_CAM);
+ dsp_mmu_write_reg(cr->ram, DSP_MMU_RAM);
+#endif
/* flush the entry */
dsp_mmu_flush();
/* load a TLB entry */
- omap_writew(DSPMMU_LD_TLB_LD, DSPMMU_LD_TLB);
+ dsp_mmu_write_reg(DSP_MMU_LD_TLB_LD, DSP_MMU_LD_TLB);
}
-static int dsp_mmu_load_tlb(unsigned long vadr, unsigned long padr,
- unsigned short slst, unsigned short prsvd,
- unsigned short ap)
+static int dsp_mmu_load_tlb(struct tlb_entry *tlb_ent)
{
- int lbase, victim;
- unsigned short cam_l_va_mask;
+ struct tlb_lock tlb_lock;
+ struct cam_ram_regset cr;
+#ifdef CONFIG_ARCH_OMAP1
clk_enable(dsp_ck_handle);
+ omap_dsp_request_mem();
+#endif
- get_tlb_lock(&lbase, NULL);
- for (victim = 0; victim < lbase; victim++) {
- unsigned short cam_l;
+ get_tlb_lock(&tlb_lock);
+ for (tlb_lock.victim = 0;
+ tlb_lock.victim < tlb_lock.base;
+ tlb_lock.victim++) {
+ struct cam_ram_regset tmp_cr;
/* read a TLB entry */
- __read_tlb(lbase, victim, NULL, &cam_l, NULL, NULL);
- if (!(cam_l & DSPMMU_CAM_L_V))
+ __read_tlb(&tlb_lock, &tmp_cr);
+ if (!cam_ram_valid(tmp_cr))
goto found_victim;
}
- set_tlb_lock(lbase, victim);
+ set_tlb_lock(&tlb_lock);
found_victim:
/* The last (31st) entry cannot be locked? */
- if (victim == 31) {
+ if (tlb_lock.victim == 31) {
printk(KERN_ERR "omapdsp: TLB is full.\n");
return -EBUSY;
}
- cam_l_va_mask = get_cam_l_va_mask(slst);
- if (vadr &
- ~(DSPMMU_CAM_H_VA_TAG_H_MASK << 22 |
- (unsigned long)cam_l_va_mask << 6)) {
+ if (tlb_ent->va & ~get_cam_va_mask(tlb_ent->pgsz)) {
printk(KERN_ERR
- "omapdsp: mapping vadr (0x%06lx) is not "
- "aligned boundary\n", vadr);
+ "omapdsp: mapping vadr (0x%06x) is not "
+ "aligned boundary\n", tlb_ent->va);
return -EINVAL;
}
- __load_tlb(vadr >> 22, (vadr >> 6 & cam_l_va_mask) | prsvd | slst,
- padr >> 16, (padr & DSPMMU_RAM_L_RAM_LSB_MASK) | ap);
+#if defined(CONFIG_ARCH_OMAP1)
+ cr.cam_h = tlb_ent->va >> 22;
+ cr.cam_l = (tlb_ent->va >> 6 & get_cam_l_va_mask(tlb_ent->pgsz)) |
+ tlb_ent->prsvd | tlb_ent->pgsz;
+ cr.ram_h = tlb_ent->pa >> 16;
+ cr.ram_l = (tlb_ent->pa & DSP_MMU_RAM_L_RAM_LSB_MASK) | tlb_ent->ap;
+#elif defined(CONFIG_ARCH_OMAP2)
+ cr.cam = (tlb_ent->va & DSP_MMU_CAM_VATAG_MASK) |
+ tlb_ent->prsvd | tlb_ent->pgsz;
+ cr.ram = tlb_ent->pa | tlb_ent->endian | tlb_ent->elsz;
+#endif
+ __load_tlb(&cr);
/* update lock base */
- if (victim == lbase)
- lbase++;
- set_tlb_lock(lbase, lbase);
+ if (tlb_lock.victim == tlb_lock.base)
+ tlb_lock.base++;
+ tlb_lock.victim = tlb_lock.base;
+ set_tlb_lock(&tlb_lock);
+#ifdef CONFIG_ARCH_OMAP1
+ omap_dsp_release_mem();
clk_disable(dsp_ck_handle);
+#endif
return 0;
}
-static int dsp_mmu_clear_tlb(unsigned long vadr)
+static int dsp_mmu_clear_tlb(dsp_long_t vadr)
{
- int lbase;
+ struct tlb_lock tlb_lock;
int i;
int max_valid = 0;
+#ifdef CONFIG_ARCH_OMAP1
clk_enable(dsp_ck_handle);
+ omap_dsp_request_mem();
+#endif
- get_tlb_lock(&lbase, NULL);
- for (i = 0; i < lbase; i++) {
- unsigned short cam_h, cam_l;
- unsigned short cam_l_va_mask, cam_vld, slst;
- unsigned long cam_va;
+ get_tlb_lock(&tlb_lock);
+ for (i = 0; i < tlb_lock.base; i++) {
+ struct cam_ram_regset cr;
+ dsp_long_t cam_va;
+ dsp_mmu_reg_t pgsz;
/* read a TLB entry */
- __read_tlb(lbase, i, &cam_h, &cam_l, NULL, NULL);
-
- cam_vld = cam_l & DSPMMU_CAM_L_V;
- if (!cam_vld)
+ tlb_lock.victim = i;
+ __read_tlb(&tlb_lock, &cr);
+ if (!cam_ram_valid(cr))
continue;
- slst = cam_l & DSPMMU_CAM_L_SLST_MASK;
- cam_l_va_mask = get_cam_l_va_mask(slst);
- cam_va = (unsigned long)(cam_h & DSPMMU_CAM_H_VA_TAG_H_MASK) << 22 |
- (unsigned long)(cam_l & cam_l_va_mask) << 6;
+#if defined(CONFIG_ARCH_OMAP1)
+ pgsz = cr.cam_l & DSP_MMU_CAM_PAGESIZE_MASK;
+ cam_va = (u32)(cr.cam_h & DSP_MMU_CAM_H_VA_TAG_H_MASK) << 22 |
+ (u32)(cr.cam_l & get_cam_l_va_mask(pgsz)) << 6;
+#elif defined(CONFIG_ARCH_OMAP2)
+ pgsz = cr.cam & DSP_MMU_CAM_PAGESIZE_MASK;
+ cam_va = cr.cam & get_cam_va_mask(pgsz);
+#endif
if (cam_va == vadr)
/* flush the entry */
}
/* set new lock base */
- set_tlb_lock(max_valid+1, max_valid+1);
+ tlb_lock.base = max_valid + 1;
+ tlb_lock.victim = max_valid + 1;
+ set_tlb_lock(&tlb_lock);
+#ifdef CONFIG_ARCH_OMAP1
+ omap_dsp_release_mem();
clk_disable(dsp_ck_handle);
+#endif
return 0;
}
static void dsp_mmu_gflush(void)
{
+ struct tlb_lock tlb_lock;
+
+#ifdef CONFIG_ARCH_OMAP1
clk_enable(dsp_ck_handle);
+ omap_dsp_request_mem();
+#endif
__dsp_mmu_gflush();
- set_tlb_lock(1, 1);
+ tlb_lock.base = exmap_preserved_cnt;
+ tlb_lock.victim = exmap_preserved_cnt;
+ set_tlb_lock(&tlb_lock);
+#ifdef CONFIG_ARCH_OMAP1
+ omap_dsp_release_mem();
clk_disable(dsp_ck_handle);
+#endif
}
/*
* dsp_exmap()
*
- * OMAP_DSP_MEM_IOCTL_EXMAP ioctl calls this function with padr=0.
+ * MEM_IOCTL_EXMAP ioctl calls this function with padr=0.
* In this case, the buffer for DSP is allocated in this routine,
* then it is mapped.
* On the other hand, for example - frame buffer sharing, calls
* this function with padr set. It means some known address space
* pointed with padr is going to be shared with DSP.
*/
-static int dsp_exmap(unsigned long dspadr, unsigned long padr,
- unsigned long size, enum exmap_type type)
+static int dsp_exmap(dsp_long_t dspadr, unsigned long padr, unsigned long size,
+ enum exmap_type_e type)
{
- unsigned short slst;
+ dsp_mmu_reg_t pgsz;
void *buf;
unsigned int order = 0;
unsigned long unit;
- unsigned int cntnu = 0;
- unsigned long _dspadr = dspadr;
+ int prev = -1;
+ dsp_long_t _dspadr = dspadr;
unsigned long _padr = padr;
void *_vadr = dspbyte_to_virt(dspadr);
unsigned long _size = size;
- struct exmap_tbl *exmap_ent;
+ struct tlb_entry tlb_ent;
+ struct exmap_tbl_entry *exmap_ent;
int status;
+ int idx;
int i;
#define MINIMUM_PAGESZ SZ_4KB
}
if (!is_aligned(dspadr, MINIMUM_PAGESZ)) {
printk(KERN_ERR
- "omapdsp: DSP address(0x%lx) is not aligned.\n", dspadr);
+ "omapdsp: DSP address(0x%x) is not aligned.\n", dspadr);
return -EINVAL;
}
if (!is_aligned(padr, MINIMUM_PAGESZ)) {
down_write(&exmap_sem);
/* overlap check */
- for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+ for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
unsigned long mapsize;
- struct exmap_tbl *tmp_ent = &exmap_tbl[i];
+ struct exmap_tbl_entry *tmp_ent = &exmap_tbl[i];
if (!tmp_ent->valid)
continue;
start:
buf = NULL;
/* Are there any free TLB lines? */
- for (i = 0; i < DSPMMU_TLB_LINES; i++) {
- if (!exmap_tbl[i].valid)
+ for (idx = 0; idx < DSP_MMU_TLB_LINES; idx++) {
+ if (!exmap_tbl[idx].valid)
goto found_free;
}
printk(KERN_ERR "omapdsp: DSP TLB is full.\n");
goto fail;
found_free:
- exmap_ent = &exmap_tbl[i];
+ exmap_ent = &exmap_tbl[idx];
+ /*
+ * we don't use
+ * 1KB mapping in OMAP1,
+ * 16MB mapping in OMAP2.
+ */
if ((_size >= SZ_1MB) &&
(is_aligned(_padr, SZ_1MB) || (padr == 0)) &&
is_aligned(_dspadr, SZ_1MB)) {
unit = SZ_1MB;
- slst = DSPMMU_CAM_L_SLST_1MB;
+ pgsz = DSP_MMU_CAM_PAGESIZE_1MB;
} else if ((_size >= SZ_64KB) &&
(is_aligned(_padr, SZ_64KB) || (padr == 0)) &&
is_aligned(_dspadr, SZ_64KB)) {
unit = SZ_64KB;
- slst = DSPMMU_CAM_L_SLST_64KB;
+ pgsz = DSP_MMU_CAM_PAGESIZE_64KB;
} else {
unit = SZ_4KB;
- slst = DSPMMU_CAM_L_SLST_4KB;
+ pgsz = DSP_MMU_CAM_PAGESIZE_4KB;
}
order = get_order(unit);
goto fail;
/* loading DSP TLB entry */
- status = dsp_mmu_load_tlb(_dspadr, _padr, slst, 0, DSPMMU_RAM_L_AP_FA);
+ INIT_TLB_ENTRY(&tlb_ent, _dspadr, _padr, pgsz);
+ status = dsp_mmu_load_tlb(&tlb_ent);
if (status < 0) {
exmap_clear_armmmu((unsigned long)_vadr, unit);
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->usecount = 0;
+ INIT_EXMAP_TBL_ENTRY(exmap_ent, buf, _vadr, type, order);
+ exmap_ent->link.prev = prev;
+ if (prev >= 0)
+ exmap_tbl[prev].link.next = idx;
if ((_size -= unit) == 0) { /* normal completion */
up_write(&exmap_sem);
_dspadr += unit;
_vadr += unit;
_padr = padr ? _padr + unit : 0;
- cntnu = 1;
+ prev = idx;
goto start;
fail:
return status;
}
-static unsigned long unmap_free_arm(struct exmap_tbl *ent)
+static unsigned long unmap_free_arm(struct exmap_tbl_entry *ent)
{
unsigned long size;
return size;
}
-static int dsp_exunmap(unsigned long dspadr)
+static int dsp_exunmap(dsp_long_t dspadr)
{
void *vadr;
unsigned long size;
int total = 0;
- struct exmap_tbl *ent;
+ struct exmap_tbl_entry *ent;
int idx;
vadr = dspbyte_to_virt(dspadr);
down_write(&exmap_sem);
- for (idx = 0; idx < DSPMMU_TLB_LINES; idx++) {
+ for (idx = 0; idx < DSP_MMU_TLB_LINES; idx++) {
ent = &exmap_tbl[idx];
- if (!ent->valid)
+ if ((!ent->valid) || ent->prsvd)
continue;
if (ent->vadr == vadr)
goto found_map;
}
up_write(&exmap_sem);
printk(KERN_WARNING
- "omapdsp: address %06lx not found in exmap_tbl.\n", dspadr);
+ "omapdsp: address %06x not found in exmap_tbl.\n", dspadr);
return -EINVAL;
found_map:
/* flush TLB */
flush_tlb_kernel_range((unsigned long)vadr, (unsigned long)vadr + size);
- /* check if next mapping is in same group */
- if (++idx == DSPMMU_TLB_LINES)
+ if ((idx = ent->link.next) < 0)
goto up_out; /* normal completion */
ent = &exmap_tbl[idx];
- if (!ent->valid || !ent->cntnu)
- goto up_out; /* normal completion */
-
dspadr += size;
vadr += size;
if (ent->vadr == vadr)
static void exmap_flush(void)
{
- struct exmap_tbl *ent;
+ struct exmap_tbl_entry *ent;
int i;
down_write(&exmap_sem);
/* clearing DSP TLB entry */
dsp_mmu_gflush();
- /* exmap_tbl[0] should be preserved */
- for (i = 1; i < DSPMMU_TLB_LINES; i++) {
+ for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
ent = &exmap_tbl[i];
- if (ent->valid) {
+ if (ent->valid && (!ent->prsvd)) {
unmap_free_arm(ent);
ent->valid = 0;
}
}
#endif
-static int dsp_fbexport(unsigned long *dspadr)
+static int dsp_fbexport(dsp_long_t *dspadr)
{
- unsigned long dspadr_actual;
+ dsp_long_t dspadr_actual;
unsigned long padr_sys, padr, fbsz_sys, fbsz;
int cnt;
#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
/* (fbsz > SZ_4KB) ? */ *dspadr;
if (dspadr_actual != *dspadr)
printk(KERN_DEBUG
- "omapdsp: actual dspadr for FBEXPORT = %08lx\n",
+ "omapdsp: actual dspadr for FBEXPORT = %08x\n",
dspadr_actual);
*dspadr = dspadr_actual;
padr_sys, fbsz_sys, padr, fbsz);
}
+#ifdef CONFIG_ARCH_OMAP1
/* increase the DMA priority */
set_emiff_dma_prio(15);
+#endif
#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
omapfb_nb = kmalloc(sizeof(struct omapfb_notifier_block), GFP_KERNEL);
#else /* CONFIG_OMAP_DSP_FBEXPORT */
-static int dsp_fbexport(unsigned long *dspadr)
+static int dsp_fbexport(dsp_long_t *dspadr)
{
printk(KERN_ERR "omapdsp: FBEXPORT function is not enabled.\n");
return -EINVAL;
#endif /* CONFIG_OMAP_DSP_FBEXPORT */
+static void exmap_setup_preserved_mem_page(void *buf, dsp_long_t dspadr,
+ int exmap_idx)
+{
+ unsigned long phys;
+ void *virt;
+ struct tlb_entry tlb_ent;
+
+ phys = __pa(buf);
+ virt = dspbyte_to_virt(dspadr);
+ exmap_set_armmmu((unsigned long)virt, phys, PAGE_SIZE);
+ INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(&exmap_tbl[exmap_idx], buf, virt);
+ INIT_TLB_ENTRY_4KB_PRESERVED(&tlb_ent, dspadr, phys);
+ dsp_mmu_load_tlb(&tlb_ent);
+}
+
+static void exmap_clear_mem_page(dsp_long_t dspadr)
+{
+ void *virt;
+
+ virt = dspbyte_to_virt(dspadr);
+ exmap_clear_armmmu((unsigned long)virt, PAGE_SIZE);
+ /* DSP MMU is shutting down. not handled here. */
+}
+
+#ifdef CONFIG_ARCH_OMAP2
+static void exmap_setup_iomap_page(unsigned long phys, unsigned long dsp_io_adr,
+ int exmap_idx)
+{
+ dsp_long_t dspadr;
+ void *virt;
+ struct tlb_entry tlb_ent;
+
+ dspadr = (IOMAP_VAL << 18) + (dsp_io_adr << 1);
+ virt = dspbyte_to_virt(dspadr);
+ exmap_set_armmmu((unsigned long)virt, phys, PAGE_SIZE);
+ INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(&exmap_tbl[exmap_idx], NULL, virt);
+ INIT_TLB_ENTRY_4KB_ES32_PRESERVED(&tlb_ent, dspadr, phys);
+ dsp_mmu_load_tlb(&tlb_ent);
+}
+
+static void exmap_clear_iomap_page(unsigned long dsp_io_adr)
+{
+ dsp_long_t dspadr;
+ void *virt;
+
+ dspadr = (IOMAP_VAL << 18) + (dsp_io_adr << 1);
+ virt = dspbyte_to_virt(dspadr);
+ exmap_clear_armmmu((unsigned long)virt, PAGE_SIZE);
+ /* DSP MMU is shutting down. not handled here. */
+}
+#endif /* CONFIG_ARCH_OMAP2 */
+
+#define OMAP2420_GPT5_BASE (L4_24XX_BASE + 0x7c000)
+#define OMAP2420_GPT6_BASE (L4_24XX_BASE + 0x7e000)
+#define OMAP2420_GPT7_BASE (L4_24XX_BASE + 0x80000)
+#define OMAP2420_GPT8_BASE (L4_24XX_BASE + 0x82000)
+#define OMAP24XX_EAC_BASE (L4_24XX_BASE + 0x90000)
+
+static int exmap_setup_preserved_entries(void)
+{
+ int n = 0;
+
+ exmap_setup_preserved_mem_page(dspvect_page, DSP_INIT_PAGE, n++);
+#ifdef CONFIG_ARCH_OMAP2
+ exmap_setup_iomap_page(OMAP24XX_PRCM_BASE, 0x7000, n++);
+#ifdef CONFIG_ARCH_OMAP2420
+ exmap_setup_iomap_page(OMAP2420_GPT5_BASE, 0xe000, n++);
+ exmap_setup_iomap_page(OMAP2420_GPT6_BASE, 0xe800, n++);
+ exmap_setup_iomap_page(OMAP2420_GPT7_BASE, 0xf000, n++);
+ exmap_setup_iomap_page(OMAP2420_GPT8_BASE, 0xf800, n++);
+#endif /* CONFIG_ARCH_OMAP2420 */
+ exmap_setup_iomap_page(OMAP24XX_EAC_BASE, 0x10000, n++);
+ exmap_setup_iomap_page(OMAP24XX_MAILBOX_BASE, 0x11000, n++);
+#endif /* CONFIG_ARCH_OMAP2 */
+
+ return n;
+}
+
+static void exmap_clear_preserved_entries(void)
+{
+ exmap_clear_mem_page(DSP_INIT_PAGE);
+#ifdef CONFIG_ARCH_OMAP2
+ exmap_clear_iomap_page(0x7000); /* PRCM */
+#ifdef CONFIG_ARCH_OMAP2420
+ exmap_clear_iomap_page(0xe000); /* GPT5 */
+ exmap_clear_iomap_page(0xe800); /* GPT6 */
+ exmap_clear_iomap_page(0xf000); /* GPT7 */
+ exmap_clear_iomap_page(0xf800); /* GPT8 */
+#endif /* CONFIG_ARCH_OMAP2420 */
+ exmap_clear_iomap_page(0x10000); /* EAC */
+ exmap_clear_iomap_page(0x11000); /* MAILBOX */
+#endif /* CONFIG_ARCH_OMAP2 */
+}
+
+#ifdef CONFIG_ARCH_OMAP1
static int dsp_mmu_itack(void)
{
unsigned long dspadr;
printk(KERN_INFO "omapdsp: sending DSP MMU interrupt ack.\n");
- if (!dsp_err_mmu_isset()) {
+ if (!dsp_err_isset(ERRCODE_MMU)) {
printk(KERN_ERR "omapdsp: DSP MMU error has not been set.\n");
return -EINVAL;
}
dspadr = dsp_fault_adr & ~(SZ_4K-1);
dsp_exmap(dspadr, 0, SZ_4K, EXMAP_TYPE_MEM); /* FIXME: reserve TLB entry for this */
printk(KERN_INFO "omapdsp: falling into recovery runlevel...\n");
- dsp_runlevel(OMAP_DSP_MBCMD_RUNLEVEL_RECOVERY);
+ dsp_set_runlevel(RUNLEVEL_RECOVERY);
__dsp_mmu_itack();
udelay(100);
dsp_exunmap(dspadr);
- dsp_err_mmu_clear();
+ dsp_err_clear(ERRCODE_MMU);
return 0;
}
+#endif /* CONFIG_ARCH_OMAP1 */
+
+#ifdef CONFIG_ARCH_OMAP2
+#define MMU_IRQ_MASK \
+ (DSP_MMU_IRQ_MULTIHITFAULT | \
+ DSP_MMU_IRQ_TABLEWALKFAULT | \
+ DSP_MMU_IRQ_EMUMISS | \
+ DSP_MMU_IRQ_TRANSLATIONFAULT | \
+ DSP_MMU_IRQ_TLBMISS)
+#endif
static void dsp_mmu_init(void)
{
- unsigned long phys;
- void *virt;
+ struct tlb_lock tlb_lock;
+#ifdef CONFIG_ARCH_OMAP1
clk_enable(dsp_ck_handle);
+ omap_dsp_request_mem();
+#endif
down_write(&exmap_sem);
+#if defined(CONFIG_ARCH_OMAP1)
dsp_mmu_disable(); /* clear all */
udelay(100);
+#elif defined(CONFIG_ARCH_OMAP2)
+ dsp_mmu_reset();
+#endif
dsp_mmu_enable();
- /* mapping for ARM MMU */
- 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].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);
- /* preserved, full access */
- dsp_mmu_load_tlb(DSP_INIT_PAGE, phys, DSPMMU_CAM_L_SLST_4KB,
- DSPMMU_CAM_L_P, DSPMMU_RAM_L_AP_FA);
+ tlb_lock.base = 0;
+ tlb_lock.victim = 0;
+ set_tlb_lock(&tlb_lock);
+
+ exmap_preserved_cnt = exmap_setup_preserved_entries();
+
+#ifdef CONFIG_ARCH_OMAP2
+ /* MMU IRQ mask setup */
+ dsp_mmu_write_reg(MMU_IRQ_MASK, DSP_MMU_IRQENABLE);
+#endif
+
up_write(&exmap_sem);
+#ifdef CONFIG_ARCH_OMAP1
+ omap_dsp_release_mem();
clk_disable(dsp_ck_handle);
+#endif
}
static void dsp_mmu_shutdown(void)
{
exmap_flush();
- dsp_mmu_disable(); /* clear all */
+ exmap_clear_preserved_entries();
+ dsp_mmu_disable();
}
+#ifdef CONFIG_ARCH_OMAP1
/*
* intmem_enable() / disable():
* if the address is in DSP internal memories,
{
int ret = 0;
- if (dsp_is_ready())
- ret = dsp_mbsend(MBCMD(PM), OMAP_DSP_MBCMD_PM_ENABLE,
- DSPREG_ICR_DMA_IDLE_DOMAIN);
+ if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
+ ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA);
return ret;
}
static void intmem_disable(void) {
- if (dsp_is_ready())
- dsp_mbsend(MBCMD(PM), OMAP_DSP_MBCMD_PM_DISABLE,
- DSPREG_ICR_DMA_IDLE_DOMAIN);
+ if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
+ mbcompose_send(PM, PM_DISABLE, DSPREG_ICR_DMA);
}
+#endif /* CONFIG_ARCH_OMAP1 */
/*
* dsp_mem_enable() / disable()
*/
+#ifdef CONFIG_ARCH_OMAP1
int intmem_usecount;
+#endif
int dsp_mem_enable(void *adr)
{
int ret = 0;
if (is_dsp_internal_mem(adr)) {
+#ifdef CONFIG_ARCH_OMAP1
if (intmem_usecount++ == 0)
ret = omap_dsp_request_mem();
+#endif
} else
down_read(&exmap_sem);
void dsp_mem_disable(void *adr)
{
if (is_dsp_internal_mem(adr)) {
+#ifdef CONFIG_ARCH_OMAP1
if (--intmem_usecount == 0)
omap_dsp_release_mem();
+#endif
} else
up_read(&exmap_sem);
}
/* for safety */
+#ifdef CONFIG_ARCH_OMAP1
void dsp_mem_usecount_clear(void)
{
if (intmem_usecount != 0) {
omap_dsp_release_mem();
}
}
+#endif /* CONFIG_ARCH_OMAP1 */
/*
* dsp_mem file operations
return ret;
}
-static ssize_t intmem_read(struct file *file, char *buf, size_t count,
+static ssize_t intmem_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
unsigned long p = *ppos;
if (p >= size)
return 0;
+#ifdef CONFIG_ARCH_OMAP1
clk_enable(api_ck_handle);
+#endif
read = count;
if (count > size - p)
read = size - p;
}
*ppos += read;
out:
+#ifdef CONFIG_ARCH_OMAP1
clk_disable(api_ck_handle);
+#endif
return read;
}
-static ssize_t exmem_read(struct file *file, char *buf, size_t count,
+static ssize_t exmem_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
unsigned long p = *ppos;
return count;
}
-static ssize_t dsp_mem_read(struct file *file, char *buf, size_t count,
+static ssize_t dsp_mem_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
int ret;
return ret;
}
-static ssize_t intmem_write(struct file *file, const char *buf, size_t count,
- loff_t *ppos)
+static ssize_t intmem_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
void *vadr = dspbyte_to_virt(p);
if (p >= size)
return 0;
+#ifdef CONFIG_ARCH_OMAP1
clk_enable(api_ck_handle);
+#endif
written = count;
if (count > size - p)
written = size - p;
}
*ppos += written;
out:
+#ifdef CONFIG_ARCH_OMAP1
clk_disable(api_ck_handle);
+#endif
return written;
}
-static ssize_t exmem_write(struct file *file, const char *buf, size_t count,
- loff_t *ppos)
+static ssize_t exmem_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
void *vadr = dspbyte_to_virt(p);
return count;
}
-static ssize_t dsp_mem_write(struct file *file, const char *buf, size_t count,
- loff_t *ppos)
+static ssize_t dsp_mem_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
{
int ret;
void *vadr = dspbyte_to_virt(*(unsigned long *)ppos);
unsigned int cmd, unsigned long arg)
{
switch (cmd) {
- case OMAP_DSP_MEM_IOCTL_MMUINIT:
+ case MEM_IOCTL_MMUINIT:
dsp_mmu_init();
return 0;
- case OMAP_DSP_MEM_IOCTL_EXMAP:
+ case MEM_IOCTL_EXMAP:
{
struct omap_dsp_mapinfo mapinfo;
- if (copy_from_user(&mapinfo, (void *)arg,
+ if (copy_from_user(&mapinfo, (void __user *)arg,
sizeof(mapinfo)))
return -EFAULT;
return dsp_exmap(mapinfo.dspadr, 0, mapinfo.size,
EXMAP_TYPE_MEM);
}
- case OMAP_DSP_MEM_IOCTL_EXUNMAP:
+ case MEM_IOCTL_EXUNMAP:
return dsp_exunmap((unsigned long)arg);
- case OMAP_DSP_MEM_IOCTL_EXMAP_FLUSH:
+ case MEM_IOCTL_EXMAP_FLUSH:
exmap_flush();
return 0;
- case OMAP_DSP_MEM_IOCTL_FBEXPORT:
+ case MEM_IOCTL_FBEXPORT:
{
- unsigned long dspadr;
+ dsp_long_t dspadr;
int ret;
- if (copy_from_user(&dspadr, (void *)arg, sizeof(long)))
+ if (copy_from_user(&dspadr, (void __user *)arg,
+ sizeof(dsp_long_t)))
return -EFAULT;
ret = dsp_fbexport(&dspadr);
- if (copy_to_user((void *)arg, &dspadr, sizeof(long)))
+ if (copy_to_user((void __user *)arg, &dspadr,
+ sizeof(dsp_long_t)))
return -EFAULT;
return ret;
}
- case OMAP_DSP_MEM_IOCTL_MMUITACK:
+#ifdef CONFIG_ARCH_OMAP1
+ case MEM_IOCTL_MMUITACK:
return dsp_mmu_itack();
+#endif
- case OMAP_DSP_MEM_IOCTL_KMEM_RESERVE:
+ case MEM_IOCTL_KMEM_RESERVE:
{
- unsigned long size;
- if (copy_from_user(&size, (void *)arg, sizeof(long)))
+ __u32 size;
+ if (copy_from_user(&size, (void __user *)arg,
+ sizeof(__u32)))
return -EFAULT;
return dsp_kmem_reserve(size);
}
- case OMAP_DSP_MEM_IOCTL_KMEM_RELEASE:
+ case MEM_IOCTL_KMEM_RELEASE:
dsp_kmem_release();
return 0;
return 0;
}
-static int dsp_mem_release(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
/*
* fb update functions:
* fbupd_response() is executed by the workqueue.
* fbupd_cb() is called when fb update is done, in interrupt context.
- * mbx1_fbupd() is called when KFUNC:FBCTL:UPD is received from DSP.
+ * mbx_fbupd() is called when KFUNC:FBCTL:UPD is received from DSP.
*/
static void fbupd_response(void *arg)
{
schedule_work(&fbupd_response_work);
}
-void mbx1_fbctl_upd(void)
+void mbx_fbctl_upd(void)
{
struct omapfb_update_window win;
volatile unsigned short *buf = ipbuf_sys_da->d;
#else /* CONFIG_FB_OMAP_LCDC_EXTERNAL */
-void mbx1_fbctl_upd(void)
+void mbx_fbctl_upd(void)
{
}
#endif /* CONFIG_FB_OMAP_LCDC_EXTERNAL */
/*
* sysfs files
*/
+
+/* mmu */
static ssize_t mmu_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int len;
- int lbase, victim;
+ struct tlb_lock tlb_lock_org;
int i;
+#ifdef CONFIG_ARCH_OMAP1
clk_enable(dsp_ck_handle);
+ omap_dsp_request_mem();
+#endif
down_read(&exmap_sem);
- get_tlb_lock(&lbase, &victim);
-
- len = sprintf(buf, "p: preserved, v: valid\n"
- "ety cam_va ram_pa sz ap\n");
- /* 00: p v 0x300000 0x10171800 64KB FA */
- for (i = 0; i < 32; i++) {
- unsigned short cam_h, cam_l, ram_h, ram_l;
- unsigned short cam_l_va_mask, prsvd, cam_vld, slst;
- unsigned long cam_va;
- unsigned short ram_l_ap;
- unsigned long ram_pa;
+ get_tlb_lock(&tlb_lock_org);
+
+#if defined(CONFIG_ARCH_OMAP1)
+ len = sprintf(buf, "P: preserved, V: valid\n"
+ "ety P V size cam_va ram_pa ap\n");
+ /* 00: P V 4KB 0x300000 0x10171800 FA */
+#elif defined(CONFIG_ARCH_OMAP2)
+ len = sprintf(buf, "P: preserved, V: valid\n"
+ "B: big endian, L:little endian, "
+ "M: mixed page attribute\n"
+ "ety P V size cam_va ram_pa E ES M\n");
+ /* 00: P V 4KB 0x300000 0x10171800 B 16 M */
+#endif
+
+ for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
+ struct cam_ram_regset cr;
+ struct tlb_lock tlb_lock_tmp;
+ struct tlb_entry ent;
+#if defined(CONFIG_ARCH_OMAP1)
char *pgsz_str, *ap_str;
+#elif defined(CONFIG_ARCH_OMAP2)
+ char *pgsz_str, *elsz_str;
+#endif
/* read a TLB entry */
- __read_tlb(lbase, i, &cam_h, &cam_l, &ram_h, &ram_l);
-
- slst = cam_l & DSPMMU_CAM_L_SLST_MASK;
- cam_l_va_mask = get_cam_l_va_mask(slst);
- pgsz_str = (slst == DSPMMU_CAM_L_SLST_1MB) ? " 1MB":
- (slst == DSPMMU_CAM_L_SLST_64KB)? "64KB":
- (slst == DSPMMU_CAM_L_SLST_4KB) ? " 4KB":
- " 1KB";
- prsvd = cam_l & DSPMMU_CAM_L_P;
- cam_vld = cam_l & DSPMMU_CAM_L_V;
- ram_l_ap = ram_l & DSPMMU_RAM_L_AP_MASK;
- ap_str = (ram_l_ap == DSPMMU_RAM_L_AP_RO) ? "RO":
- (ram_l_ap == DSPMMU_RAM_L_AP_FA) ? "FA":
- "NA";
- cam_va = (unsigned long)(cam_h & DSPMMU_CAM_H_VA_TAG_H_MASK) << 22 |
- (unsigned long)(cam_l & cam_l_va_mask) << 6;
- ram_pa = (unsigned long)ram_h << 16 |
- (ram_l & DSPMMU_RAM_L_RAM_LSB_MASK);
-
- if (i == lbase)
- len += sprintf(buf + len, "lock base = %d\n", lbase);
- if (i == victim)
- len += sprintf(buf + len, "victim = %d\n", victim);
- /* 00: p v 0x300000 0x10171800 64KB FA */
+ tlb_lock_tmp.base = tlb_lock_org.base;
+ tlb_lock_tmp.victim = i;
+ __read_tlb(&tlb_lock_tmp, &cr);
+
+#if defined(CONFIG_ARCH_OMAP1)
+ ent.pgsz = cr.cam_l & DSP_MMU_CAM_PAGESIZE_MASK;
+ ent.prsvd = cr.cam_l & DSP_MMU_CAM_P;
+ ent.valid = cr.cam_l & DSP_MMU_CAM_V;
+ ent.ap = cr.ram_l & DSP_MMU_RAM_L_AP_MASK;
+ ent.va = (u32)(cr.cam_h & DSP_MMU_CAM_H_VA_TAG_H_MASK) << 22 |
+ (u32)(cr.cam_l & get_cam_l_va_mask(ent.pgsz)) << 6;
+ ent.pa = (unsigned long)cr.ram_h << 16 |
+ (cr.ram_l & DSP_MMU_RAM_L_RAM_LSB_MASK);
+
+ pgsz_str = (ent.pgsz == DSP_MMU_CAM_PAGESIZE_1MB) ? " 1MB":
+ (ent.pgsz == DSP_MMU_CAM_PAGESIZE_64KB) ? "64KB":
+ (ent.pgsz == DSP_MMU_CAM_PAGESIZE_4KB) ? " 4KB":
+ (ent.pgsz == DSP_MMU_CAM_PAGESIZE_1KB) ? " 1KB":
+ " ???";
+ ap_str = (ent.ap == DSP_MMU_RAM_L_AP_RO) ? "RO":
+ (ent.ap == DSP_MMU_RAM_L_AP_FA) ? "FA":
+ (ent.ap == DSP_MMU_RAM_L_AP_NA) ? "NA":
+ "??";
+#elif defined(CONFIG_ARCH_OMAP2)
+ ent.pgsz = cr.cam & DSP_MMU_CAM_PAGESIZE_MASK;
+ ent.prsvd = cr.cam & DSP_MMU_CAM_P;
+ ent.valid = cr.cam & DSP_MMU_CAM_V;
+ ent.va = cr.cam & DSP_MMU_CAM_VATAG_MASK;
+ ent.endian = cr.ram & DSP_MMU_RAM_ENDIANNESS;
+ ent.elsz = cr.ram & DSP_MMU_RAM_ELEMENTSIZE_MASK;
+ ent.pa = cr.ram & DSP_MMU_RAM_PADDR_MASK;
+ ent.mixed = cr.ram & DSP_MMU_RAM_MIXED;
+
+ pgsz_str = (ent.pgsz == DSP_MMU_CAM_PAGESIZE_16MB) ? "64MB":
+ (ent.pgsz == DSP_MMU_CAM_PAGESIZE_1MB) ? " 1MB":
+ (ent.pgsz == DSP_MMU_CAM_PAGESIZE_64KB) ? "64KB":
+ (ent.pgsz == DSP_MMU_CAM_PAGESIZE_4KB) ? " 4KB":
+ " ???";
+ elsz_str = (ent.elsz == DSP_MMU_RAM_ELEMENTSIZE_8) ? " 8":
+ (ent.elsz == DSP_MMU_RAM_ELEMENTSIZE_16) ? "16":
+ (ent.elsz == DSP_MMU_RAM_ELEMENTSIZE_32) ? "32":
+ "??";
+#endif
+
+ if (i == tlb_lock_org.base)
+ len += sprintf(buf + len, "lock base = %d\n",
+ tlb_lock_org.base);
+ if (i == tlb_lock_org.victim)
+ len += sprintf(buf + len, "victim = %d\n",
+ tlb_lock_org.victim);
+#if defined(CONFIG_ARCH_OMAP1)
+ len += sprintf(buf + len,
+ /* 00: P V 4KB 0x300000 0x10171800 FA */
+ "%02d: %c %c %s 0x%06x 0x%08lx %s\n",
+ i,
+ ent.prsvd ? 'P' : ' ',
+ ent.valid ? 'V' : ' ',
+ pgsz_str, ent.va, ent.pa, ap_str);
+#elif defined(CONFIG_ARCH_OMAP2)
len += sprintf(buf + len,
- "%02d: %c %c 0x%06lx 0x%08lx %s %s\n",
+ /* 00: P V 4KB 0x300000 0x10171800 B 16 M */
+ "%02d: %c %c %s 0x%06x 0x%08lx %c %s %c\n",
i,
- prsvd ? 'p' : ' ',
- cam_vld ? 'v' : ' ',
- cam_va, ram_pa, pgsz_str, ap_str);
+ ent.prsvd ? 'P' : ' ',
+ ent.valid ? 'V' : ' ',
+ pgsz_str, ent.va, ent.pa,
+ ent.endian ? 'B' : 'L',
+ elsz_str,
+ ent.mixed ? 'M' : ' ');
+#endif /* CONFIG_ARCH_OMAP2 */
}
/* restore victim entry */
- set_tlb_lock(lbase, victim);
+ set_tlb_lock(&tlb_lock_org);
up_read(&exmap_sem);
+#ifdef CONFIG_ARCH_OMAP1
+ omap_dsp_release_mem();
clk_disable(dsp_ck_handle);
+#endif
return len;
}
-static struct device_attribute dev_attr_mmu = __ATTR_RO(mmu);
-
+/* exmap */
static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int i;
down_read(&exmap_sem);
- len = sprintf(buf, "v: valid, c: cntnu\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 %2d\n",
- i,
- ent->valid ? 'v' : ' ',
- ent->cntnu ? 'c' : ' ',
- ent->vadr, ent->buf, ent->order, ent->usecount);
+ len = sprintf(buf, " dspadr size buf size uc\n");
+ /* 0x300000 0x123000 0xc0171000 0x100000 0*/
+ for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
+ struct exmap_tbl_entry *ent = &exmap_tbl[i];
+ void *vadr;
+ unsigned long size;
+ enum exmap_type_e type;
+ int idx;
+
+ /* find a top of link */
+ if (!ent->valid || (ent->link.prev >= 0))
+ continue;
+
+ vadr = ent->vadr;
+ type = ent->type;
+ size = 0;
+ idx = i;
+ do {
+ ent = &exmap_tbl[idx];
+ size += PAGE_SIZE << ent->order;
+ } while ((idx = ent->link.next) >= 0);
+
+ len += sprintf(buf + len, "0x%06x %#8lx",
+ virt_to_dspbyte(vadr), size);
+
+ if (type == EXMAP_TYPE_FB) {
+ len += sprintf(buf + len, " framebuf\n");
+ } else {
+ len += sprintf(buf + len, "\n");
+ idx = i;
+ do {
+ ent = &exmap_tbl[idx];
+ len += sprintf(buf + len,
+ /* 0xc0171000 0x100000 0*/
+ "%19s0x%8p %#8lx %2d\n",
+ "", ent->buf,
+ PAGE_SIZE << ent->order,
+ ent->usecount);
+ } while ((idx = ent->link.next) >= 0);
+ }
}
up_read(&exmap_sem);
return len;
}
-static struct device_attribute dev_attr_exmap = __ATTR_RO(exmap);
-
-static ssize_t kmem_pool_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+/* mempool */
+static ssize_t mempool_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- int nr_1M, nr_64K, total;
+ int min_nr_1M = 0, curr_nr_1M = 0;
+ int min_nr_64K = 0, curr_nr_64K = 0;
+ int total = 0;
- nr_1M = kmem_pool_1M->min_nr;
- nr_64K = kmem_pool_64K->min_nr;
- total = nr_1M * SZ_1MB + nr_64K * SZ_64KB;
+ if (likely(kmem_pool_1M)) {
+ min_nr_1M = kmem_pool_1M->min_nr;
+ curr_nr_1M = kmem_pool_1M->curr_nr;
+ total += min_nr_1M * SZ_1MB;
+ }
+ if (likely(kmem_pool_64K)) {
+ min_nr_64K = kmem_pool_64K->min_nr;
+ curr_nr_64K = kmem_pool_64K->curr_nr;
+ total += min_nr_64K * SZ_64KB;
+ }
- return sprintf(buf, "0x%x %d %d\n", total, nr_1M, nr_64K);
+ return sprintf(buf,
+ "0x%x\n"
+ "1M buffer: %d (%d free)\n"
+ "64K buffer: %d (%d free)\n",
+ total, min_nr_1M, curr_nr_1M, min_nr_64K, curr_nr_64K);
}
-static struct device_attribute dev_attr_kmem_pool = __ATTR_RO(kmem_pool);
-
/*
- * DSP MMU interrupt handler
+ * workqueue for mmu int
*/
-
+#ifdef CONFIG_ARCH_OMAP1
/*
* MMU fault mask:
* We ignore prefetch err.
*/
#define MMUFAULT_MASK \
- (DSPMMU_FAULT_ST_PERM |\
- DSPMMU_FAULT_ST_TLB_MISS |\
- DSPMMU_FAULT_ST_TRANS)
-irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned short status;
- unsigned short adh, adl;
- unsigned short dp;
-
- status = omap_readw(DSPMMU_FAULT_ST);
- adh = omap_readw(DSPMMU_FAULT_AD_H);
- adl = omap_readw(DSPMMU_FAULT_AD_L);
- dp = adh & DSPMMU_FAULT_AD_H_DP;
- dsp_fault_adr = MKLONG(adh & DSPMMU_FAULT_AD_H_ADR_MASK, adl);
+ (DSP_MMU_FAULT_ST_PERM |\
+ DSP_MMU_FAULT_ST_TLB_MISS |\
+ DSP_MMU_FAULT_ST_TRANS)
+#endif /* CONFIG_ARCH_OMAP1 */
+
+static void do_mmu_int(void)
+{
+#if defined(CONFIG_ARCH_OMAP1)
+
+ dsp_mmu_reg_t status;
+ dsp_mmu_reg_t adh, adl;
+ dsp_mmu_reg_t dp;
+
+ status = dsp_mmu_read_reg(DSP_MMU_FAULT_ST);
+ adh = dsp_mmu_read_reg(DSP_MMU_FAULT_AD_H);
+ adl = dsp_mmu_read_reg(DSP_MMU_FAULT_AD_L);
+ dp = adh & DSP_MMU_FAULT_AD_H_DP;
+ dsp_fault_adr = MK32(adh & DSP_MMU_FAULT_AD_H_ADR_MASK, adl);
+
/* if the fault is masked, nothing to do */
if ((status & MMUFAULT_MASK) == 0) {
printk(KERN_DEBUG "DSP MMU interrupt, but ignoring.\n");
/*
* note: in OMAP1710,
* when CACHE + DMA domain gets out of idle in DSP,
- * MMU interrupt occurs but DSPMMU_FAULT_ST is not set.
+ * MMU interrupt occurs but DSP_MMU_FAULT_ST is not set.
* in this case, we just ignore the interrupt.
*/
if (status) {
printk(KERN_DEBUG "%s%s%s%s\n",
- (status & DSPMMU_FAULT_ST_PREF)?
+ (status & DSP_MMU_FAULT_ST_PREF)?
" (prefetch err)" : "",
- (status & DSPMMU_FAULT_ST_PERM)?
+ (status & DSP_MMU_FAULT_ST_PERM)?
" (permission fault)" : "",
- (status & DSPMMU_FAULT_ST_TLB_MISS)?
+ (status & DSP_MMU_FAULT_ST_TLB_MISS)?
" (TLB miss)" : "",
- (status & DSPMMU_FAULT_ST_TRANS) ?
+ (status & DSP_MMU_FAULT_ST_TRANS) ?
" (translation fault)": "");
- printk(KERN_DEBUG
- "fault address = %s: 0x%06lx\n",
- dp ? "DATA" : "PROGRAM",
+ printk(KERN_DEBUG "fault address = %#08x\n",
dsp_fault_adr);
}
- return IRQ_HANDLED;
+ enable_irq(INT_DSP_MMU);
+ return;
}
+#elif defined(CONFIG_ARCH_OMAP2)
+
+ dsp_mmu_reg_t status;
+
+ status = dsp_mmu_read_reg(DSP_MMU_IRQSTATUS);
+ dsp_fault_adr = dsp_mmu_read_reg(DSP_MMU_FAULT_AD);
+
+#endif /* CONFIG_ARCH_OMAP2 */
+
printk(KERN_INFO "DSP MMU interrupt!\n");
+
+#if defined(CONFIG_ARCH_OMAP1)
+
printk(KERN_INFO "%s%s%s%s\n",
- (status & DSPMMU_FAULT_ST_PREF)?
- (MMUFAULT_MASK & DSPMMU_FAULT_ST_PREF)?
+ (status & DSP_MMU_FAULT_ST_PREF)?
+ (MMUFAULT_MASK & DSP_MMU_FAULT_ST_PREF)?
" prefetch err":
" (prefetch err)":
"",
- (status & DSPMMU_FAULT_ST_PERM)?
- (MMUFAULT_MASK & DSPMMU_FAULT_ST_PERM)?
+ (status & DSP_MMU_FAULT_ST_PERM)?
+ (MMUFAULT_MASK & DSP_MMU_FAULT_ST_PERM)?
" permission fault":
" (permission fault)":
"",
- (status & DSPMMU_FAULT_ST_TLB_MISS)?
- (MMUFAULT_MASK & DSPMMU_FAULT_ST_TLB_MISS)?
+ (status & DSP_MMU_FAULT_ST_TLB_MISS)?
+ (MMUFAULT_MASK & DSP_MMU_FAULT_ST_TLB_MISS)?
" TLB miss":
" (TLB miss)":
"",
- (status & DSPMMU_FAULT_ST_TRANS)?
- (MMUFAULT_MASK & DSPMMU_FAULT_ST_TRANS)?
+ (status & DSP_MMU_FAULT_ST_TRANS)?
+ (MMUFAULT_MASK & DSP_MMU_FAULT_ST_TRANS)?
" translation fault":
" (translation fault)":
"");
- printk(KERN_INFO "fault address = %s: 0x%06lx\n",
- dp ? "DATA" : "PROGRAM",
- dsp_fault_adr);
- if (dsp_is_ready()) {
- /*
- * If we call dsp_exmap() here,
- * "kernel BUG at slab.c" occurs.
- */
- /* FIXME */
- dsp_err_mmu_set(dsp_fault_adr);
- } else {
- disable_irq(INT_DSP_MMU);
+#elif defined(CONFIG_ARCH_OMAP2)
+
+ printk(KERN_INFO "%s%s%s%s%s\n",
+ (status & DSP_MMU_IRQ_MULTIHITFAULT)?
+ (MMU_IRQ_MASK & DSP_MMU_IRQ_MULTIHITFAULT)?
+ " multi hit":
+ " (multi hit)":
+ "",
+ (status & DSP_MMU_IRQ_TABLEWALKFAULT)?
+ (MMU_IRQ_MASK & DSP_MMU_IRQ_TABLEWALKFAULT)?
+ " table walk fault":
+ " (table walk fault)":
+ "",
+ (status & DSP_MMU_IRQ_EMUMISS)?
+ (MMU_IRQ_MASK & DSP_MMU_IRQ_EMUMISS)?
+ " EMU miss":
+ " (EMU miss)":
+ "",
+ (status & DSP_MMU_IRQ_TRANSLATIONFAULT)?
+ (MMU_IRQ_MASK & DSP_MMU_IRQ_TRANSLATIONFAULT)?
+ " translation fault":
+ " (translation fault)":
+ "",
+ (status & DSP_MMU_IRQ_TLBMISS)?
+ (MMU_IRQ_MASK & DSP_MMU_IRQ_TLBMISS)?
+ " TLB miss":
+ " (TLB miss)":
+ "");
+
+#endif /* CONFIG_ARCH_OMAP2 */
+
+ printk(KERN_INFO "fault address = %#08x\n", dsp_fault_adr);
+
+ if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
+ dsp_err_set(ERRCODE_MMU, (unsigned long)dsp_fault_adr);
+ else {
+#ifdef CONFIG_ARCH_OMAP1
__dsp_mmu_itack();
+#endif
printk(KERN_INFO "Resetting DSP...\n");
dsp_cpustat_request(CPUSTAT_RESET);
- enable_irq(INT_DSP_MMU);
/*
* if we enable followings, semaphore lock should be avoided.
*
*/
}
+#ifdef CONFIG_ARCH_OMAP2
+ dsp_mmu_disable();
+ dsp_mmu_write_reg(status, DSP_MMU_IRQSTATUS);
+ dsp_mmu_enable();
+#endif
+
+ enable_irq(INT_DSP_MMU);
+}
+
+static DECLARE_WORK(mmu_int_work, (void (*)(void *))do_mmu_int, NULL);
+
+/*
+ * DSP MMU interrupt handler
+ */
+
+static irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ disable_irq(INT_DSP_MMU);
+ schedule_work(&mmu_int_work);
return IRQ_HANDLED;
}
.ioctl = dsp_mem_ioctl,
.mmap = dsp_mem_mmap,
.open = dsp_mem_open,
- .release = dsp_mem_release,
};
void dsp_mem_start(void)
{
+#ifdef CONFIG_ARCH_OMAP1
dsp_register_mem_cb(intmem_enable, intmem_disable);
+#endif
}
void dsp_mem_stop(void)
{
memset(&mem_sync, 0, sizeof(struct mem_sync_struct));
+#ifdef CONFIG_ARCH_OMAP1
dsp_unregister_mem_cb();
+#endif
}
+static char devid_mmu;
+
int __init dsp_mem_init(void)
{
int i;
+ int ret = 0;
+#ifdef CONFIG_ARCH_OMAP2
+ int dspmem_pg_count;
- for (i = 0; i < DSPMMU_TLB_LINES; i++) {
- exmap_tbl[i].valid = 0;
+ dspmem_pg_count = dspmem_size >> 12;
+ for (i = 0; i < dspmem_pg_count; i++) {
+ dsp_ipi_write_reg(i, DSP_IPI_INDEX);
+ dsp_ipi_write_reg(DSP_IPI_ENTRY_ELMSIZEVALUE_16, DSP_IPI_ENTRY);
}
+ dsp_ipi_write_reg(1, DSP_IPI_ENABLE);
+
+ dsp_ipi_write_reg(IOMAP_VAL, DSP_IPI_IOMAP);
+#endif
+
+ for (i = 0; i < DSP_MMU_TLB_LINES; i++)
+ exmap_tbl[i].valid = 0;
dspvect_page = (void *)__get_dma_pages(GFP_KERNEL, 0);
if (dspvect_page == NULL) {
return -ENOMEM;
}
dsp_mmu_init();
+#ifdef CONFIG_ARCH_OMAP1
dsp_set_idle_boot_base(IDLEPG_BASE, IDLEPG_SIZE);
+#endif
+
+ /*
+ * DSP MMU interrupt setup
+ */
+ ret = request_irq(INT_DSP_MMU, dsp_mmu_interrupt, SA_INTERRUPT, "dsp",
+ &devid_mmu);
+ if (ret) {
+ printk(KERN_ERR
+ "failed to register DSP MMU interrupt: %d\n", ret);
+ goto fail;
+ }
+
+ /* MMU interrupt is not enabled until DSP runs */
+ disable_irq(INT_DSP_MMU);
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);
+ device_create_file(&dsp_device.dev, &dev_attr_mempool);
return 0;
+
+fail:
+#ifdef CONFIG_ARCH_OMAP1
+ dsp_reset_idle_boot_base();
+#endif
+ dsp_mmu_shutdown();
+ free_page((unsigned long)dspvect_page);
+ dspvect_page = NULL;
+ return ret;
}
void dsp_mem_exit(void)
{
+ free_irq(INT_DSP_MMU, &devid_mmu);
+
+ /* recover disable_depth */
+ enable_irq(INT_DSP_MMU);
+
+#ifdef CONFIG_ARCH_OMAP1
+ dsp_reset_idle_boot_base();
+#endif
dsp_mmu_shutdown();
dsp_kmem_release();
if (dspvect_page != NULL) {
- unsigned long virt;
-
- 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;
-
- 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);
+ device_remove_file(&dsp_device.dev, &dev_attr_mempool);
}
/*
- * linux/arch/arm/mach-omap/dsp/error.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * OMAP DSP error detection I/F device driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/03/11: DSP Gateway version 3.3
*/
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/major.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/ioctls.h>
-#include <asm/arch/dsp.h>
+#include "dsp_mbcmd.h"
#include "dsp.h"
+/*
+ * value seen through read()
+ */
+#define DSP_ERR_WDT 0x00000001
+#define DSP_ERR_MMU 0x00000002
+static unsigned long errval;
+
static DECLARE_WAIT_QUEUE_HEAD(err_wait_q);
-static unsigned long errcode;
static int errcnt;
-static unsigned short wdtval; /* FIXME: read through ioctl */
-static unsigned long mmu_fadr; /* FIXME: read through ioctl */
+static u16 wdtval; /* FIXME: read through ioctl */
+static u32 mmu_fadr; /* FIXME: read through ioctl */
/*
* DSP error detection device file operations
*/
-static ssize_t dsp_err_read(struct file *file, char *buf, size_t count,
+static ssize_t dsp_err_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
unsigned long flags;
}
local_irq_save(flags);
- status = copy_to_user(buf, &errcode, 4);
+ status = copy_to_user(buf, &errval, 4);
if (status) {
local_irq_restore(flags);
return -EFAULT;
};
/*
- * DSP MMU
+ * set / clear functions
*/
-void dsp_err_mmu_set(unsigned long adr)
+
+/* DSP MMU */
+static void dsp_err_mmu_set(unsigned long arg)
{
disable_irq(INT_DSP_MMU);
- errcode |= OMAP_DSP_ERRDT_MMU;
- errcnt++;
- mmu_fadr = adr;
- wake_up_interruptible(&err_wait_q);
+ mmu_fadr = (u32)arg;
}
-void dsp_err_mmu_clear(void)
+static void dsp_err_mmu_clr(void)
{
- errcode &= ~OMAP_DSP_ERRDT_MMU;
enable_irq(INT_DSP_MMU);
}
-int dsp_err_mmu_isset(void)
+/* WDT */
+static void dsp_err_wdt_set(unsigned long arg)
{
- return (errcode & OMAP_DSP_ERRDT_MMU) ? 1 : 0;
+ wdtval = (u16)arg;
}
/*
- * WDT
+ * error code handler
*/
-void dsp_err_wdt_clear(void)
+static struct {
+ unsigned long val;
+ void (*set)(unsigned long arg);
+ void (*clr)(void);
+} dsp_err_desc[ERRCODE_MAX] = {
+ [ERRCODE_MMU] = { DSP_ERR_MMU, dsp_err_mmu_set, dsp_err_mmu_clr },
+ [ERRCODE_WDT] = { DSP_ERR_WDT, dsp_err_wdt_set, NULL },
+};
+
+void dsp_err_set(enum errcode_e code, unsigned long arg)
{
- errcode &= ~OMAP_DSP_ERRDT_WDT;
+ if (dsp_err_desc[code].set != NULL)
+ dsp_err_desc[code].set(arg);
+
+ errval |= dsp_err_desc[code].val;
+ errcnt++;
+ wake_up_interruptible(&err_wait_q);
+}
+
+void dsp_err_clear(enum errcode_e code)
+{
+ errval &= ~dsp_err_desc[code].val;
+
+ if (dsp_err_desc[code].clr != NULL)
+ dsp_err_desc[code].clr();
}
-int dsp_err_wdt_isset(void)
+int dsp_err_isset(enum errcode_e code)
{
- return (errcode & OMAP_DSP_ERRDT_WDT) ? 1 : 0;
+ return (errval & dsp_err_desc[code].val) ? 1 : 0;
}
/*
- * functions called from mailbox1 interrupt routine
+ * functions called from mailbox interrupt routine
*/
-static void mbx1_err_wdt(unsigned short data)
+static void mbx_err_wdt(u16 data)
{
- errcode |= OMAP_DSP_ERRDT_WDT;
- errcnt++;
- wdtval = data;
- wake_up_interruptible(&err_wait_q);
+ dsp_err_set(DSP_ERR_WDT, (unsigned long)data);
}
#ifdef OLD_BINARY_SUPPORT
/* v3.3 obsolete */
-void mbx1_wdt(struct mbcmd *mb)
+void mbx_wdt(struct mbcmd *mb)
{
- mbx1_err_wdt(mb->data);
+ mbx_err_wdt(mb->data);
}
#endif
-extern void mbx1_err_ipbfull(void);
-extern void mbx1_err_fatal(unsigned char tid);
+extern void mbx_err_ipbfull(void);
+extern void mbx_err_fatal(u8 tid);
-void mbx1_err(struct mbcmd *mb)
+void mbx_err(struct mbcmd *mb)
{
- unsigned char eid = mb->cmd_l;
+ u8 eid = mb->cmd_l;
char *eidnm = subcmd_name(mb);
- unsigned char tid;
+ u8 tid;
if (eidnm) {
printk(KERN_WARNING
}
switch (eid) {
- case OMAP_DSP_EID_IPBFULL:
- mbx1_err_ipbfull();
+ case EID_IPBFULL:
+ mbx_err_ipbfull();
break;
- case OMAP_DSP_EID_FATAL:
+ case EID_FATAL:
tid = mb->data & 0x00ff;
- mbx1_err_fatal(tid);
+ mbx_err_fatal(tid);
break;
- case OMAP_DSP_EID_WDT:
- mbx1_err_wdt(mb->data);
+ case EID_WDT:
+ mbx_err_wdt(mb->data);
break;
}
}
*/
void dsp_err_start(void)
{
+ enum errcode_e i;
+
+ for (i = 0; i < ERRCODE_MAX; i++) {
+ if (dsp_err_isset(i))
+ dsp_err_clear(i);
+ }
+
errcnt = 0;
- if (dsp_err_wdt_isset())
- dsp_err_wdt_clear();
- if (dsp_err_mmu_isset())
- dsp_err_mmu_clear();
}
void dsp_err_stop(void)
/*
- * linux/arch/arm/mach-omap/dsp/fifo.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * FIFO buffer operators
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/02/24: DSP Gateway version 3.3
*/
struct fifo_struct {
static inline void free_fifo(struct fifo_struct *fifo)
{
spin_lock(&fifo->lock);
- if (fifo->buf == NULL)
+ if (fifo->buf == NULL) {
+ spin_unlock(&fifo->lock);
return;
+ }
kfree(fifo->buf);
fifo->buf = NULL;
kfree(fifo->buf);
/* alloc */
- if ((fifo->buf = kmalloc(sz, GFP_KERNEL)) == NULL) {
- fifo->sz = 0;
- ret = -ENOMEM;
- goto out;
- }
- fifo->sz = sz;
- fifo->cnt = 0;
- fifo->wp = 0;
+ ret = alloc_fifo(fifo, sz);
out:
spin_unlock(&fifo->lock);
return ret;
}
-static inline void write_word_to_fifo(struct fifo_struct *fifo,
- unsigned short word)
+static inline void write_word_to_fifo(struct fifo_struct *fifo, u16 word)
{
spin_lock(&fifo->lock);
- *(unsigned short *)&fifo->buf[fifo->wp] = word;
+ *(u16 *)&fifo->buf[fifo->wp] = word;
if ((fifo->wp += 2) == fifo->sz)
fifo->wp = 0;
if ((fifo->cnt += 2) > fifo->sz)
/*
- * linux/arch/arm/mach-omap/dsp/hardware_dsp.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * Register bit definitions for DSP driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/05/30: DSP Gateway version 3.3
*/
#ifndef __OMAP_DSP_HARDWARE_DSP_H
#define __OMAP_DSP_HARDWARE_DSP_H
-#ifdef CONFIG_ARCH_OMAP15XX
-#define OMAP1510_DARAM_BASE 0xe0000000
-#define OMAP1510_DARAM_SIZE 0x10000
-#define OMAP1510_SARAM_BASE 0xe0010000
-#define OMAP1510_SARAM_SIZE 0x18000
+#ifdef CONFIG_ARCH_OMAP1
+#include "omap1_dsp.h"
#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
+#ifdef CONFIG_ARCH_OMAP2
+#include "omap2_dsp.h"
#endif
-/*
- * MAJOR device number: !! allocated arbitrary !!
- */
-#define OMAP_DSP_CTL_MAJOR 96
-#define OMAP_DSP_TASK_MAJOR 97
-
-/*
- * Reset Control
- */
-#define ARM_RSTCT1_SW_RST 0x0008
-#define ARM_RSTCT1_DSP_RST 0x0004
-#define ARM_RSTCT1_DSP_EN 0x0002
-#define ARM_RSTCT1_ARM_RST 0x0001
-
-/*
- * MPUI
- */
-#define MPUI_CTRL_WORDSWAP_MASK 0x00600000
-#define MPUI_CTRL_WORDSWAP_ALL 0x00000000
-#define MPUI_CTRL_WORDSWAP_NONAPI 0x00200000
-#define MPUI_CTRL_WORDSWAP_API 0x00400000
-#define MPUI_CTRL_WORDSWAP_NONE 0x00600000
-#define MPUI_CTRL_AP_MASK 0x001c0000
-#define MPUI_CTRL_AP_MDH 0x00000000
-#define MPUI_CTRL_AP_MHD 0x00040000
-#define MPUI_CTRL_AP_DMH 0x00080000
-#define MPUI_CTRL_AP_HMD 0x000c0000
-#define MPUI_CTRL_AP_DHM 0x00100000
-#define MPUI_CTRL_AP_HDM 0x00140000
-#define MPUI_CTRL_BYTESWAP_MASK 0x00030000
-#define MPUI_CTRL_BYTESWAP_NONE 0x00000000
-#define MPUI_CTRL_BYTESWAP_NONAPI 0x00010000
-#define MPUI_CTRL_BYTESWAP_ALL 0x00020000
-#define MPUI_CTRL_BYTESWAP_API 0x00030000
-#define MPUI_CTRL_TIMEOUT_MASK 0x0000ff00
-#define MPUI_CTRL_APIF_HNSTB_DIV_MASK 0x000000f0
-#define MPUI_CTRL_S_NABORT_GL 0x00000008
-#define MPUI_CTRL_S_NABORT_32BIT 0x00000004
-#define MPUI_CTRL_EN_TIMEOUT 0x00000002
-#define MPUI_CTRL_HF_MCUCLK 0x00000001
-#define MPUI_DSP_BOOT_CONFIG_DIRECT 0x00000000
-#define MPUI_DSP_BOOT_CONFIG_PSD_DIRECT 0x00000001
-#define MPUI_DSP_BOOT_CONFIG_IDLE 0x00000002
-#define MPUI_DSP_BOOT_CONFIG_DL16 0x00000003
-#define MPUI_DSP_BOOT_CONFIG_DL32 0x00000004
-#define MPUI_DSP_BOOT_CONFIG_MPUI 0x00000005
-#define MPUI_DSP_BOOT_CONFIG_INTERNAL 0x00000006
-
-/*
- * DSP boot mode
- * direct: 0xffff00
- * pseudo direct: 0x080000
- * MPUI: branch 0x010000
- * internel: branch 0x024000
- */
-#define DSP_BOOT_ADR_DIRECT 0xffff00
-#define DSP_BOOT_ADR_PSD_DIRECT 0x080000
-#define DSP_BOOT_ADR_MPUI 0x010000
-#define DSP_BOOT_ADR_INTERNAL 0x024000
-
-/*
- * TC
- */
-#define TC_ENDIANISM_SWAP 0x00000002
-#define TC_ENDIANISM_SWAP_WORD 0x00000002
-#define TC_ENDIANISM_SWAP_BYTE 0x00000000
-#define TC_ENDIANISM_EN 0x00000001
-
-/*
- * DSP MMU
- */
-#define DSPMMU_BASE (0xfffed200)
-#define DSPMMU_PREFETCH (DSPMMU_BASE + 0x00)
-#define DSPMMU_WALKING_ST (DSPMMU_BASE + 0x04)
-#define DSPMMU_CNTL (DSPMMU_BASE + 0x08)
-#define DSPMMU_FAULT_AD_H (DSPMMU_BASE + 0x0c)
-#define DSPMMU_FAULT_AD_L (DSPMMU_BASE + 0x10)
-#define DSPMMU_FAULT_ST (DSPMMU_BASE + 0x14)
-#define DSPMMU_IT_ACK (DSPMMU_BASE + 0x18)
-#define DSPMMU_TTB_H (DSPMMU_BASE + 0x1c)
-#define DSPMMU_TTB_L (DSPMMU_BASE + 0x20)
-#define DSPMMU_LOCK (DSPMMU_BASE + 0x24)
-#define DSPMMU_LD_TLB (DSPMMU_BASE + 0x28)
-#define DSPMMU_CAM_H (DSPMMU_BASE + 0x2c)
-#define DSPMMU_CAM_L (DSPMMU_BASE + 0x30)
-#define DSPMMU_RAM_H (DSPMMU_BASE + 0x34)
-#define DSPMMU_RAM_L (DSPMMU_BASE + 0x38)
-#define DSPMMU_GFLUSH (DSPMMU_BASE + 0x3c)
-#define DSPMMU_FLUSH_ENTRY (DSPMMU_BASE + 0x40)
-#define DSPMMU_READ_CAM_H (DSPMMU_BASE + 0x44)
-#define DSPMMU_READ_CAM_L (DSPMMU_BASE + 0x48)
-#define DSPMMU_READ_RAM_H (DSPMMU_BASE + 0x4c)
-#define DSPMMU_READ_RAM_L (DSPMMU_BASE + 0x50)
-
-#define DSPMMU_CNTL_BURST_16MNGT_EN 0x0020
-#define DSPMMU_CNTL_WTL_EN 0x0004
-#define DSPMMU_CNTL_MMU_EN 0x0002
-#define DSPMMU_CNTL_RESET_SW 0x0001
-
-#define DSPMMU_FAULT_AD_H_DP 0x0100
-#define DSPMMU_FAULT_AD_H_ADR_MASK 0x00ff
-
-#define DSPMMU_FAULT_ST_PREF 0x0008
-#define DSPMMU_FAULT_ST_PERM 0x0004
-#define DSPMMU_FAULT_ST_TLB_MISS 0x0002
-#define DSPMMU_FAULT_ST_TRANS 0x0001
-
-#define DSPMMU_IT_ACK_IT_ACK 0x0001
-
-#define DSPMMU_LOCK_BASE_MASK 0xfc00
-#define DSPMMU_LOCK_BASE_SHIFT 10
-#define DSPMMU_LOCK_VICTIM_MASK 0x03f0
-#define DSPMMU_LOCK_VICTIM_SHIFT 4
-
-#define DSPMMU_CAM_H_VA_TAG_H_MASK 0x0003
-
-#define DSPMMU_CAM_L_VA_TAG_L1_MASK 0xc000
-#define DSPMMU_CAM_L_VA_TAG_L2_MASK_1MB 0x0000
-#define DSPMMU_CAM_L_VA_TAG_L2_MASK_64KB 0x3c00
-#define DSPMMU_CAM_L_VA_TAG_L2_MASK_4KB 0x3fc0
-#define DSPMMU_CAM_L_VA_TAG_L2_MASK_1KB 0x3ff0
-#define DSPMMU_CAM_L_P 0x0008
-#define DSPMMU_CAM_L_V 0x0004
-#define DSPMMU_CAM_L_SLST_MASK 0x0003
-#define DSPMMU_CAM_L_SLST_1MB 0x0000
-#define DSPMMU_CAM_L_SLST_64KB 0x0001
-#define DSPMMU_CAM_L_SLST_4KB 0x0002
-#define DSPMMU_CAM_L_SLST_1KB 0x0003
-
-#define DSPMMU_RAM_L_RAM_LSB_MASK 0xfc00
-#define DSPMMU_RAM_L_AP_MASK 0x0300
-#define DSPMMU_RAM_L_AP_NA 0x0000
-#define DSPMMU_RAM_L_AP_RO 0x0200
-#define DSPMMU_RAM_L_AP_FA 0x0300
-
-#define DSPMMU_GFLUSH_GFLUSH 0x0001
-
-#define DSPMMU_FLUSH_ENTRY_FLUSH_ENTRY 0x0001
-
-#define DSPMMU_LD_TLB_RD 0x0002
-#define DSPMMU_LD_TLB_LD 0x0001
-
-/*
- * Mailbox
- */
-#define MAILBOX_BASE (0xfffcf000)
-#define MAILBOX_ARM2DSP1 (MAILBOX_BASE + 0x00)
-#define MAILBOX_ARM2DSP1b (MAILBOX_BASE + 0x04)
-#define MAILBOX_DSP2ARM1 (MAILBOX_BASE + 0x08)
-#define MAILBOX_DSP2ARM1b (MAILBOX_BASE + 0x0c)
-#define MAILBOX_DSP2ARM2 (MAILBOX_BASE + 0x10)
-#define MAILBOX_DSP2ARM2b (MAILBOX_BASE + 0x14)
-#define MAILBOX_ARM2DSP1_Flag (MAILBOX_BASE + 0x18)
-#define MAILBOX_DSP2ARM1_Flag (MAILBOX_BASE + 0x1c)
-#define MAILBOX_DSP2ARM2_Flag (MAILBOX_BASE + 0x20)
-
-/*
- * 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
-#define DSPREG_ICR_CACHE_IDLE_DOMAIN 0x0004
-#define DSPREG_ICR_DMA_IDLE_DOMAIN 0x0002
-#define DSPREG_ICR_CPU_IDLE_DOMAIN 0x0001
-
#endif /* __OMAP_DSP_HARDWARE_DSP_H */
--- /dev/null
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+/*
+ * for /dev/dspctl/ctl
+ */
+#define DSPCTL_IOCTL_RESET 1
+#define DSPCTL_IOCTL_RUN 2
+#define DSPCTL_IOCTL_SETRSTVECT 3
+#ifdef CONFIG_ARCH_OMAP1
+#define DSPCTL_IOCTL_CPU_IDLE 4
+#define DSPCTL_IOCTL_MPUI_WORDSWAP_ON 5
+#define DSPCTL_IOCTL_MPUI_WORDSWAP_OFF 6
+#define DSPCTL_IOCTL_MPUI_BYTESWAP_ON 7
+#define DSPCTL_IOCTL_MPUI_BYTESWAP_OFF 8
+#define DSPCTL_IOCTL_GBL_IDLE 9
+#endif /* CONFIG_ARCH_OMAP1 */
+#define DSPCTL_IOCTL_DSPCFG 10
+#define DSPCTL_IOCTL_DSPUNCFG 11
+#define DSPCTL_IOCTL_TASKCNT 12
+#define DSPCTL_IOCTL_POLL 13
+#define DSPCTL_IOCTL_REGMEMR 40
+#define DSPCTL_IOCTL_REGMEMW 41
+#define DSPCTL_IOCTL_REGIOR 42
+#define DSPCTL_IOCTL_REGIOW 43
+#define DSPCTL_IOCTL_GETVAR 44
+#define DSPCTL_IOCTL_SETVAR 45
+#define DSPCTL_IOCTL_RUNLEVEL 50
+#define DSPCTL_IOCTL_SUSPEND 51
+#define DSPCTL_IOCTL_RESUME 52
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+#define DSPCTL_IOCTL_FBEN 53
+#define DSPCTL_IOCTL_FBDIS 54
+#endif /* CONFIG_OMAP_DSP_FBEXPORT */
+#define DSPCTL_IOCTL_MBSEND 99
+
+struct omap_dsp_mailbox_cmd {
+ __u16 cmd;
+ __u16 data;
+};
+
+struct omap_dsp_reginfo {
+ __u16 adr;
+ __u16 val;
+};
+
+struct omap_dsp_varinfo {
+ __u8 varid;
+ __u16 val[0];
+};
+
+/*
+ * for taskdev
+ * (ioctls below should be >= 0x10000)
+ */
+#define TASK_IOCTL_BFLSH 0x10000
+#define TASK_IOCTL_SETBSZ 0x10001
+#define TASK_IOCTL_LOCK 0x10002
+#define TASK_IOCTL_UNLOCK 0x10003
+#define TASK_IOCTL_GETNAME 0x10004
+
+/*
+ * for /dev/dspctl/mem
+ */
+#define MEM_IOCTL_EXMAP 1
+#define MEM_IOCTL_EXUNMAP 2
+#define MEM_IOCTL_EXMAP_FLUSH 3
+#define MEM_IOCTL_FBEXPORT 5
+#ifdef CONFIG_ARCH_OMAP1
+#define MEM_IOCTL_MMUITACK 7
+#endif
+#define MEM_IOCTL_MMUINIT 9
+#define MEM_IOCTL_KMEM_RESERVE 11
+#define MEM_IOCTL_KMEM_RELEASE 12
+
+struct omap_dsp_mapinfo {
+ __u32 dspadr;
+ __u32 size;
+};
+
+/*
+ * for /dev/dspctl/twch
+ */
+#define TWCH_IOCTL_MKDEV 1
+#define TWCH_IOCTL_RMDEV 2
+#define TWCH_IOCTL_TADD 11
+#define TWCH_IOCTL_TDEL 12
+#define TWCH_IOCTL_TKILL 13
+
+struct omap_dsp_taddinfo {
+ __u8 minor;
+ __u32 taskadr;
+};
+
+#define TADD_ABORTADR 0xffffffff
/*
- * linux/arch/arm/mach-omap/dsp/ipbuf.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * IPBUF handler
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/06/06: DSP Gateway version 3.3
*/
-#include <linux/init.h>
#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
#include <linux/device.h>
-#include <asm/signal.h>
-#include <asm/arch/dsp.h>
+#include <asm/arch/mailbox.h>
+#include "dsp_mbcmd.h"
#include "dsp.h"
#include "ipbuf.h"
-struct ipbuf **ipbuf;
+static struct ipbuf_head *g_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;
+static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static struct device_attribute dev_attr_ipbuf = __ATTR_RO(ipbuf);
+
void ipbuf_stop(void)
{
int i;
+ device_remove_file(&dsp_device.dev, &dev_attr_ipbuf);
+
spin_lock(&ipb_free.lock);
- INIT_IPBLINK(&ipb_free);
+ RESET_IPBLINK(&ipb_free);
spin_unlock(&ipb_free.lock);
ipbcfg.ln = 0;
- if (ipbuf) {
- kfree(ipbuf);
- ipbuf = NULL;
+ if (g_ipbuf) {
+ kfree(g_ipbuf);
+ g_ipbuf = NULL;
}
for (i = 0; i < ipbuf_sys_hold_mem_active; i++) {
dsp_mem_disable((void *)daram_base);
ipbuf_sys_hold_mem_active = 0;
}
-int ipbuf_config(unsigned short ln, unsigned short lsz, void *base)
+int ipbuf_config(u16 ln, u16 lsz, void *base)
{
- unsigned long lsz_byte = ((unsigned long)lsz) << 1;
+ size_t lsz_byte = ((size_t)lsz) << 1;
size_t size;
int ret = 0;
int i;
if (dsp_address_validate(base, size, "global ipbuf") < 0)
return -EINVAL;
- ipbuf = kmalloc(sizeof(void *) * ln, GFP_KERNEL);
- if (ipbuf == NULL) {
+ g_ipbuf = kmalloc(sizeof(struct ipbuf_head) * ln, GFP_KERNEL);
+ if (g_ipbuf == NULL) {
printk(KERN_ERR
"omapdsp: memory allocation for ipbuf failed.\n");
return -ENOMEM;
top = base + (sizeof(struct ipbuf) + lsz_byte) * i;
btm = base + (sizeof(struct ipbuf) + lsz_byte) * (i+1) - 1;
- ipbuf[i] = (struct ipbuf *)top;
+ g_ipbuf[i].p = (struct ipbuf *)top;
+ g_ipbuf[i].bid = i;
if (((unsigned long)top & 0xfffe0000) !=
((unsigned long)btm & 0xfffe0000)) {
/*
*/
printk(KERN_ERR
"omapdsp: ipbuf[%d] crosses 64k-word boundary!\n"
- " @0x%p, size=0x%08lx\n", i, top, lsz_byte);
+ " @0x%p, size=0x%08x\n", i, top, lsz_byte);
ret = -EINVAL;
goto free_out;
}
" %d words * %d lines at 0x%p.\n",
ipbcfg.lsz, ipbcfg.ln, ipbcfg.base);
+ device_create_file(&dsp_device.dev, &dev_attr_ipbuf);
+
return ret;
free_out:
- kfree(ipbuf);
- ipbuf = NULL;
+ kfree(g_ipbuf);
+ g_ipbuf = NULL;
return ret;
}
-int ipbuf_sys_config(void *p, enum arm_dsp_dir dir)
+int ipbuf_sys_config(void *p, enum arm_dsp_dir_e dir)
{
char *dir_str = (dir == DIR_D2A) ? "D2A" : "A2D";
return 0;
}
-int ipbuf_p_validate(void *p, enum arm_dsp_dir dir)
+int ipbuf_p_validate(void *p, enum arm_dsp_dir_e dir)
{
char *dir_str = (dir == DIR_D2A) ? "D2A" : "A2D";
/*
* Global IPBUF operations
*/
-unsigned short get_free_ipbuf(unsigned char tid)
+struct ipbuf_head *bid_to_ipbuf(u16 bid)
{
- unsigned short bid;
+ return &g_ipbuf[bid];
+}
+
+struct ipbuf_head *get_free_ipbuf(u8 tid)
+{
+ struct ipbuf_head *ipb_h;
if (dsp_mem_enable_ipbuf() < 0)
- return OMAP_DSP_BID_NULL;
+ return NULL;
spin_lock(&ipb_free.lock);
if (ipblink_empty(&ipb_free)) {
/* FIXME: wait on queue when not available. */
- bid = OMAP_DSP_BID_NULL;
+ ipb_h = NULL;
goto out;
}
- bid = ipb_free.top;
- ipbuf[bid]->la = tid; /* lock */
- ipblink_del_top(&ipb_free, ipbuf);
+ ipb_h = &g_ipbuf[ipb_free.top];
+ ipb_h->p->la = tid; /* lock */
+ __ipblink_del_top(&ipb_free);
out:
spin_unlock(&ipb_free.lock);
dsp_mem_disable_ipbuf();
- return bid;
+ return ipb_h;
}
-void release_ipbuf(unsigned short bid)
+void release_ipbuf(struct ipbuf_head *ipb_h)
{
- if (ipbuf[bid]->la == OMAP_DSP_TID_FREE) {
+ if (ipb_h->p->la == TID_FREE) {
printk(KERN_WARNING
"omapdsp: attempt to release unlocked IPBUF[%d].\n",
- bid);
+ ipb_h->bid);
/*
* FIXME: re-calc bsycnt
*/
return;
}
- ipbuf[bid]->la = OMAP_DSP_TID_FREE;
- ipbuf[bid]->sa = OMAP_DSP_TID_FREE;
- spin_lock(&ipb_free.lock);
- ipblink_add_tail(&ipb_free, bid, ipbuf);
- spin_unlock(&ipb_free.lock);
+ ipb_h->p->la = TID_FREE;
+ ipb_h->p->sa = TID_FREE;
+ ipblink_add_tail(&ipb_free, ipb_h->bid);
}
-static int try_yld(unsigned short bid)
+static int try_yld(struct ipbuf_head *ipb_h)
{
int status;
- ipbuf[bid]->sa = OMAP_DSP_TID_ANON;
- status = dsp_mbsend(MBCMD(BKYLD), 0, bid);
+ ipb_h->p->sa = TID_ANON;
+ status = mbcompose_send(BKYLD, 0, ipb_h->bid);
if (status < 0) {
/* DSP is busy and ARM keeps this line. */
- release_ipbuf(bid);
+ release_ipbuf(ipb_h);
return status;
}
static void do_balance_ipbuf(void)
{
while (ipbcfg.bsycnt <= ipbcfg.ln / 4) {
- unsigned short bid;
+ struct ipbuf_head *ipb_h;
- bid = get_free_ipbuf(OMAP_DSP_TID_ANON);
- if (bid == OMAP_DSP_BID_NULL)
+ if ((ipb_h = get_free_ipbuf(TID_ANON)) == NULL)
return;
- if (try_yld(bid) < 0)
+ if (try_yld(ipb_h) < 0)
return;
}
}
}
/* for process context */
-void unuse_ipbuf(unsigned short bid)
+void unuse_ipbuf(struct ipbuf_head *ipb_h)
{
if (ipbcfg.bsycnt > ipbcfg.ln / 4) {
/* we don't have enough IPBUF lines. let's keep it. */
- release_ipbuf(bid);
+ release_ipbuf(ipb_h);
} else {
/* we have enough IPBUF lines. let's return this line to DSP. */
- ipbuf[bid]->la = OMAP_DSP_TID_ANON;
- try_yld(bid);
+ ipb_h->p->la = TID_ANON;
+ try_yld(ipb_h);
balance_ipbuf();
}
}
/* for interrupt context */
-void unuse_ipbuf_nowait(unsigned short bid)
+void unuse_ipbuf_nowait(struct ipbuf_head *ipb_h)
{
- release_ipbuf(bid);
+ release_ipbuf(ipb_h);
balance_ipbuf();
}
/*
- * functions called from mailbox1 interrupt routine
+ * functions called from mailbox interrupt routine
*/
-void mbx1_err_ipbfull(void)
+void mbx_err_ipbfull(void)
{
ipbcfg.cnt_full++;
}
char *buf)
{
int len = 0;
- unsigned short bid;
+ u16 bid;
for (bid = 0; bid < ipbcfg.ln; bid++) {
- unsigned short la = ipbuf[bid]->la;
- unsigned short ld = ipbuf[bid]->ld;
- unsigned short c = ipbuf[bid]->c;
+ struct ipbuf_head *ipb_h = &g_ipbuf[bid];
+ u16 la = ipb_h->p->la;
+ u16 ld = ipb_h->p->ld;
+ u16 c = ipb_h->p->c;
if (len > PAGE_SIZE - 100) {
len += sprintf(buf + len, "out of buffer.\n");
}
len += sprintf(buf + len, "ipbuf[%d]: adr = 0x%p\n",
- bid, ipbuf[bid]);
- if (la == OMAP_DSP_TID_FREE) {
+ bid, ipb_h->p);
+ if (la == TID_FREE) {
len += sprintf(buf + len,
" DSPtask[%d]->Linux "
"(already read and now free for Linux)\n",
ld);
- } else if (ld == OMAP_DSP_TID_FREE) {
+ } else if (ld == TID_FREE) {
len += sprintf(buf + len,
" Linux->DSPtask[%d] "
"(already read and now free for DSP)\n",
len += sprintf(buf + len, "\nFree IPBUF link: ");
spin_lock(&ipb_free.lock);
- ipblink_for_each(bid, &ipb_free, ipbuf) {
+ ipblink_for_each(bid, &ipb_free) {
len += sprintf(buf + len, "%d ", bid);
}
spin_unlock(&ipb_free.lock);
finish:
return len;
}
-
-struct device_attribute dev_attr_ipbuf = __ATTR_RO(ipbuf);
/*
- * linux/arch/arm/mach-omap/dsp/ipbuf.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * Header for IPBUF
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/05/17: DSP Gateway version 3.3
*/
struct ipbuf {
- unsigned short c; /* count */
- unsigned short next; /* link */
- unsigned short la; /* lock owner (ARM side) */
- unsigned short sa; /* sync word (ARM->DSP) */
- unsigned short ld; /* lock owner (DSP side) */
- unsigned short sd; /* sync word (DSP->ARM) */
+ u16 c; /* count */
+ u16 next; /* link */
+ u16 la; /* lock owner (ARM side) */
+ u16 sa; /* sync word (ARM->DSP) */
+ u16 ld; /* lock owner (DSP side) */
+ u16 sd; /* sync word (DSP->ARM) */
unsigned char d[0]; /* data */
};
struct ipbuf_p {
- unsigned short c; /* count */
- unsigned short s; /* sync word */
- unsigned short al; /* data address lower */
- unsigned short ah; /* data address upper */
+ u16 c; /* count */
+ u16 s; /* sync word */
+ u16 al; /* data address lower */
+ u16 ah; /* data address upper */
};
+#define IPBUF_SYS_DLEN 31
+
struct ipbuf_sys {
- unsigned short s; /* sync word */
- unsigned short d[31]; /* data */
+ u16 s; /* sync word */
+ u16 d[IPBUF_SYS_DLEN]; /* data */
};
struct ipbcfg {
- unsigned short ln;
- unsigned short lsz;
+ u16 ln;
+ u16 lsz;
void *base;
- unsigned short bsycnt;
+ u16 bsycnt;
unsigned long cnt_full; /* count of IPBFULL error */
};
-extern struct ipbuf **ipbuf;
+struct ipbuf_head {
+ u16 bid;
+ struct ipbuf *p;
+};
+
extern struct ipbcfg ipbcfg;
extern struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
#define ipb_bsycnt_inc(ipbcfg) \
do { \
- disable_irq(INT_D2A_MB1); \
+ disable_mbx_irq(mbx_dsp); \
(ipbcfg)->bsycnt++; \
- enable_irq(INT_D2A_MB1); \
+ enable_mbx_irq(mbx_dsp); \
} while(0)
#define ipb_bsycnt_dec(ipbcfg) \
do { \
- disable_irq(INT_D2A_MB1); \
+ disable_mbx_irq(mbx_dsp); \
(ipbcfg)->bsycnt--; \
- enable_irq(INT_D2A_MB1); \
+ enable_mbx_irq(mbx_dsp); \
} while(0)
#define dsp_mem_enable_ipbuf() dsp_mem_enable(ipbcfg.base)
struct ipblink {
spinlock_t lock;
- unsigned short top;
- unsigned short tail;
+ u16 top;
+ u16 tail;
};
#define IPBLINK_INIT { \
.lock = SPIN_LOCK_UNLOCKED, \
- .top = OMAP_DSP_BID_NULL, \
- .tail = OMAP_DSP_BID_NULL, \
+ .top = BID_NULL, \
+ .tail = BID_NULL, \
}
#define INIT_IPBLINK(link) \
do { \
spin_lock_init(&(link)->lock); \
- (link)->top = OMAP_DSP_BID_NULL; \
- (link)->tail = OMAP_DSP_BID_NULL; \
+ (link)->top = BID_NULL; \
+ (link)->tail = BID_NULL; \
} while(0)
-#define ipblink_empty(link) ((link)->top == OMAP_DSP_BID_NULL)
+#define RESET_IPBLINK(link) \
+ do { \
+ (link)->top = BID_NULL; \
+ (link)->tail = BID_NULL; \
+ } while(0)
+
+#define ipblink_empty(link) ((link)->top == BID_NULL)
-static __inline__ void ipblink_del_top(struct ipblink *link,
- struct ipbuf **ipbuf)
+static __inline__ void __ipblink_del_top(struct ipblink *link)
{
- struct ipbuf *bufp = ipbuf[link->top];
+ struct ipbuf_head *ipb_h = bid_to_ipbuf(link->top);
- if ((link->top = bufp->next) == OMAP_DSP_BID_NULL)
- link->tail = OMAP_DSP_BID_NULL;
+ if ((link->top = ipb_h->p->next) == BID_NULL)
+ link->tail = BID_NULL;
else
- bufp->next = OMAP_DSP_BID_NULL;
+ ipb_h->p->next = BID_NULL;
}
-static __inline__ void ipblink_add_tail(struct ipblink *link,
- unsigned short bid,
- struct ipbuf **ipbuf)
+static __inline__ void ipblink_del_top(struct ipblink *link)
+{
+ spin_lock(&link->lock);
+ __ipblink_del_top(link);
+ spin_unlock(&link->lock);
+}
+
+static __inline__ void __ipblink_add_tail(struct ipblink *link, u16 bid)
{
if (ipblink_empty(link))
link->top = bid;
else
- ipbuf[link->tail]->next = bid;
+ bid_to_ipbuf(link->tail)->p->next = bid;
link->tail = bid;
}
+static __inline__ void ipblink_add_tail(struct ipblink *link, u16 bid)
+{
+ spin_lock(&link->lock);
+ __ipblink_add_tail(link, bid);
+ spin_unlock(&link->lock);
+}
+
+static __inline__ void __ipblink_flush(struct ipblink *link)
+{
+ u16 bid;
+
+ while (!ipblink_empty(link)) {
+ bid = link->top;
+ __ipblink_del_top(link);
+ unuse_ipbuf(bid_to_ipbuf(bid));
+ }
+}
+
+static __inline__ void ipblink_flush(struct ipblink *link)
+{
+ spin_lock(&link->lock);
+ __ipblink_flush(link);
+ spin_unlock(&link->lock);
+}
+
+static __inline__ void __ipblink_add_pvt(struct ipblink *link)
+{
+ link->top = BID_PVT;
+ link->tail = BID_PVT;
+}
+
static __inline__ void ipblink_add_pvt(struct ipblink *link)
{
- link->top = OMAP_DSP_BID_PVT;
- link->tail = OMAP_DSP_BID_PVT;
+ spin_lock(&link->lock);
+ __ipblink_add_pvt(link);
+ spin_unlock(&link->lock);
+}
+
+static __inline__ void __ipblink_del_pvt(struct ipblink *link)
+{
+ link->top = BID_NULL;
+ link->tail = BID_NULL;
}
static __inline__ void ipblink_del_pvt(struct ipblink *link)
{
- link->top = OMAP_DSP_BID_NULL;
- link->tail = OMAP_DSP_BID_NULL;
+ spin_lock(&link->lock);
+ __ipblink_del_pvt(link);
+ spin_unlock(&link->lock);
+}
+
+static __inline__ void __ipblink_flush_pvt(struct ipblink *link)
+{
+ if (!ipblink_empty(link))
+ ipblink_del_pvt(link);
+}
+
+static __inline__ void ipblink_flush_pvt(struct ipblink *link)
+{
+ spin_lock(&link->lock);
+ __ipblink_flush_pvt(link);
+ spin_unlock(&link->lock);
}
-#define ipblink_for_each(bid, link, ipbuf) \
- for (bid = (link)->top; bid != OMAP_DSP_BID_NULL; bid = ipbuf[bid]->next)
+#define ipblink_for_each(bid, link) \
+ for (bid = (link)->top; bid != BID_NULL; bid = bid_to_ipbuf(bid)->p->next)
/*
- * linux/arch/arm/mach-omap/dsp/mblog.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * OMAP DSP driver Mailbox log module
+ * Copyright (C) 2003-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2003-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/05/18: DSP Gateway version 3.3
*/
-#include <linux/module.h>
-#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/init.h>
-#include <asm/irq.h>
-#include <asm/arch/dsp.h>
+#include <asm/arch/mailbox.h>
+#include "dsp_mbcmd.h"
#include "dsp.h"
-#define RLCMD(nm) OMAP_DSP_MBCMD_RUNLEVEL_##nm
-#define KFUNCCMD(nm) OMAP_DSP_MBCMD_KFUNC_##nm
-#define PMCMD(nm) OMAP_DSP_MBCMD_PM_##nm
-#define CFGCMD(nm) OMAP_DSP_MBCMD_DSPCFG_##nm
-#define REGCMD(nm) OMAP_DSP_MBCMD_REGRW_##nm
-#define VICMD(nm) OMAP_DSP_MBCMD_VARID_##nm
-#define EID(nm) OMAP_DSP_EID_##nm
-
char *subcmd_name(struct mbcmd *mb)
{
- unsigned char cmd_h = mb->cmd_h;
- unsigned char cmd_l = mb->cmd_l;
+ u8 cmd_h = mb->cmd_h;
+ u8 cmd_l = mb->cmd_l;
char *s;
switch (cmd_h) {
- case MBCMD(RUNLEVEL):
- s = (cmd_l == RLCMD(USER)) ? "USER":
- (cmd_l == RLCMD(SUPER)) ? "SUPER":
- (cmd_l == RLCMD(RECOVERY)) ? "RECOVERY":
+ case MBX_CMD_DSP_RUNLEVEL:
+ s = (cmd_l == RUNLEVEL_USER) ? "USER":
+ (cmd_l == RUNLEVEL_SUPER) ? "SUPER":
+ (cmd_l == RUNLEVEL_RECOVERY) ? "RECOVERY":
NULL;
break;
- case MBCMD(PM):
- s = (cmd_l == PMCMD(DISABLE)) ? "DISABLE":
- (cmd_l == PMCMD(ENABLE)) ? "ENABLE":
+ case MBX_CMD_DSP_PM:
+ s = (cmd_l == PM_DISABLE) ? "DISABLE":
+ (cmd_l == PM_ENABLE) ? "ENABLE":
NULL;
break;
- case MBCMD(KFUNC):
- s = (cmd_l == KFUNCCMD(FBCTL)) ? "FBCTL":
- (cmd_l == KFUNCCMD(AUDIO_PWR)) ? "AUDIO_PWR":
+ case MBX_CMD_DSP_KFUNC:
+ s = (cmd_l == KFUNC_FBCTL) ? "FBCTL":
NULL;
break;
- case MBCMD(DSPCFG):
+ case MBX_CMD_DSP_DSPCFG:
{
- unsigned char cfgc = cmd_l & 0x7f;
- s = (cfgc == CFGCMD(REQ)) ? "REQ":
- (cfgc == CFGCMD(SYSADRH)) ? "SYSADRH":
- (cfgc == CFGCMD(SYSADRL)) ? "SYSADRL":
- (cfgc == CFGCMD(ABORT)) ? "ABORT":
- (cfgc == CFGCMD(PROTREV)) ? "PROTREV":
+ u8 cfgc = cmd_l & 0x7f;
+ s = (cfgc == DSPCFG_REQ) ? "REQ":
+ (cfgc == DSPCFG_SYSADRH) ? "SYSADRH":
+ (cfgc == DSPCFG_SYSADRL) ? "SYSADRL":
+ (cfgc == DSPCFG_ABORT) ? "ABORT":
+ (cfgc == DSPCFG_PROTREV) ? "PROTREV":
NULL;
break;
}
- case MBCMD(REGRW):
- s = (cmd_l == REGCMD(MEMR)) ? "MEMR":
- (cmd_l == REGCMD(MEMW)) ? "MEMW":
- (cmd_l == REGCMD(IOR)) ? "IOR":
- (cmd_l == REGCMD(IOW)) ? "IOW":
- (cmd_l == REGCMD(DATA)) ? "DATA":
+ case MBX_CMD_DSP_REGRW:
+ s = (cmd_l == REGRW_MEMR) ? "MEMR":
+ (cmd_l == REGRW_MEMW) ? "MEMW":
+ (cmd_l == REGRW_IOR) ? "IOR":
+ (cmd_l == REGRW_IOW) ? "IOW":
+ (cmd_l == REGRW_DATA) ? "DATA":
NULL;
break;
- case MBCMD(GETVAR):
- case MBCMD(SETVAR):
- s = (cmd_l == VICMD(ICRMASK)) ? "ICRMASK":
- (cmd_l == VICMD(LOADINFO)) ? "LOADINFO":
+ case MBX_CMD_DSP_GETVAR:
+ case MBX_CMD_DSP_SETVAR:
+ s = (cmd_l == VARID_ICRMASK) ? "ICRMASK":
+ (cmd_l == VARID_LOADINFO) ? "LOADINFO":
NULL;
break;
- case MBCMD(ERR):
- s = (cmd_l == EID(BADTID)) ? "BADTID":
- (cmd_l == EID(BADTCN)) ? "BADTCN":
- (cmd_l == EID(BADBID)) ? "BADBID":
- (cmd_l == EID(BADCNT)) ? "BADCNT":
- (cmd_l == EID(NOTLOCKED)) ? "NOTLOCKED":
- (cmd_l == EID(STVBUF)) ? "STVBUF":
- (cmd_l == EID(BADADR)) ? "BADADR":
- (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":
- (cmd_l == EID(TASKNOTRDY)) ? "TASKNOTRDY":
- (cmd_l == EID(TASKBSY)) ? "TASKBSY":
- (cmd_l == EID(TASKERR)) ? "TASKERR":
- (cmd_l == EID(BADCFGTYP)) ? "BADCFGTYP":
- (cmd_l == EID(DEBUG)) ? "DEBUG":
- (cmd_l == EID(BADSEQ)) ? "BADSEQ":
- (cmd_l == EID(BADCMD)) ? "BADCMD":
+ case MBX_CMD_DSP_ERR:
+ s = (cmd_l == EID_BADTID) ? "BADTID":
+ (cmd_l == EID_BADTCN) ? "BADTCN":
+ (cmd_l == EID_BADBID) ? "BADBID":
+ (cmd_l == EID_BADCNT) ? "BADCNT":
+ (cmd_l == EID_NOTLOCKED) ? "NOTLOCKED":
+ (cmd_l == EID_STVBUF) ? "STVBUF":
+ (cmd_l == EID_BADADR) ? "BADADR":
+ (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":
+ (cmd_l == EID_TASKNOTRDY) ? "TASKNOTRDY":
+ (cmd_l == EID_TASKBSY) ? "TASKBSY":
+ (cmd_l == EID_TASKERR) ? "TASKERR":
+ (cmd_l == EID_BADCFGTYP) ? "BADCFGTYP":
+ (cmd_l == EID_DEBUG) ? "DEBUG":
+ (cmd_l == EID_BADSEQ) ? "BADSEQ":
+ (cmd_l == EID_BADCMD) ? "BADCMD":
NULL;
break;
default:
struct mblogent {
unsigned long jiffies;
- unsigned short cmd;
- unsigned short data;
- enum arm_dsp_dir dir;
+ mbx_msg_t msg;
+ enum arm_dsp_dir_e dir;
};
static struct {
int wp;
unsigned long cnt, cnt_ad, cnt_da;
struct mblogent ent[MBLOG_DEPTH];
-} mblog;
+} mblog = {
+ .lock = SPIN_LOCK_UNLOCKED,
+};
-void mblog_add(struct mbcmd *mb, enum arm_dsp_dir dir)
+void mblog_add(struct mbcmd *mb, enum arm_dsp_dir_e dir)
{
- struct mbcmd_hw *mb_hw = (struct mbcmd_hw *)mb;
struct mblogent *ent;
spin_lock(&mblog.lock);
ent = &mblog.ent[mblog.wp];
ent->jiffies = jiffies;
- ent->cmd = mb_hw->cmd;
- ent->data = mb_hw->data;
- ent->dir = dir;
+ ent->msg = *(mbx_msg_t *)mb;
+ ent->dir = dir;
if (mblog.cnt < 0xffffffff)
mblog.cnt++;
switch (dir) {
if (mblog.cnt == 0)
goto done;
- len += sprintf(buf + len, " ARM -> DSP ARM <- DSP\n");
- len += sprintf(buf + len, "jiffies q cmd data q cmd data\n");
+ len += sprintf(buf + len, " ARM->DSP ARM<-DSP\n");
+ len += sprintf(buf + len, " jiffies cmd data cmd data\n");
i = (mblog.cnt >= MBLOG_DEPTH) ? wp : 0;
do {
struct mblogent *ent = &mblog.ent[i];
- union {
- struct mbcmd sw;
- struct mbcmd_hw hw;
- } mb = {
- .hw.cmd = ent->cmd,
- .hw.data = ent->data
- };
+ struct mbcmd *mb = (struct mbcmd *)&ent->msg;
char *subname;
- const struct cmdinfo *ci = cmdinfo[mb.sw.cmd_h];
+ struct cmdinfo ci_null = {
+ .name = "Unknown",
+ .cmd_l_type = CMD_L_TYPE_NULL,
+ };
+ const struct cmdinfo *ci;
len += sprintf(buf + len,
(ent->dir == DIR_A2D) ?
- "%08lx %d %04x %04x ":
- "%08lx %d %04x %04x ",
- ent->jiffies, mb.sw.seq, ent->cmd, ent->data);
+ "%08lx %04x %04x ":
+ "%08lx %04x %04x ",
+ ent->jiffies,
+ (ent->msg >> 16) & 0x7fff, ent->msg & 0xffff);
+
+ if ((ci = cmdinfo[mb->cmd_h]) == NULL)
+ ci = &ci_null;
+
switch (ci->cmd_l_type) {
case CMD_L_TYPE_SUBCMD:
- if ((subname = subcmd_name(&mb.sw)) == NULL)
+ if ((subname = subcmd_name(mb)) == NULL)
subname = "Unknown";
len += sprintf(buf + len, "%s:%s\n",
ci->name, subname);
break;
case CMD_L_TYPE_TID:
len += sprintf(buf + len, "%s:task %d\n",
- ci->name, mb.sw.cmd_l);
+ ci->name, mb->cmd_l);
break;
case CMD_L_TYPE_NULL:
len += sprintf(buf + len, "%s\n", ci->name);
static struct device_attribute dev_attr_mblog = __ATTR_RO(mblog);
#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
-void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir dir)
+void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir_e dir)
{
- const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
+ struct cmdinfo ci_null = {
+ .name = "Unknown",
+ .cmd_l_type = CMD_L_TYPE_NULL,
+ };
+ const struct cmdinfo *ci;
char *dir_str;
char *subname;
dir_str = (dir == DIR_A2D) ? "sending" : "receiving";
+
+ if ((ci = cmdinfo[mb->cmd_h]) == NULL)
+ ci = &ci_null;
+
switch (ci->cmd_l_type) {
case CMD_L_TYPE_SUBCMD:
if ((subname = subcmd_name(mb)) == NULL)
subname = "Unknown";
printk(KERN_DEBUG
- "mbx: %s seq=%d, cmd=%02x:%02x(%s:%s), data=%04x\n",
- dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
+ "mbx: %s cmd=%02x:%02x(%s:%s), data=%04x\n",
+ dir_str, mb->cmd_h, mb->cmd_l,
ci->name, subname, mb->data);
break;
case CMD_L_TYPE_TID:
printk(KERN_DEBUG
- "mbx: %s seq=%d, cmd=%02x:%02x(%s:task %d), data=%04x\n",
- dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
+ "mbx: %s cmd=%02x:%02x(%s:task %d), data=%04x\n",
+ dir_str, mb->cmd_h, mb->cmd_l,
ci->name, mb->cmd_l, mb->data);
break;
case CMD_L_TYPE_NULL:
printk(KERN_DEBUG
- "mbx: %s seq=%d, cmd=%02x:%02x(%s), data=%04x\n",
- dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
- ci->name, mb->data);
+ "mbx: %s cmd=%02x:%02x(%s), data=%04x\n",
+ dir_str, mb->cmd_h, mb->cmd_l, ci->name, mb->data);
break;
}
}
void __init mblog_init(void)
{
- spin_lock_init(&mblog.lock);
device_create_file(&dsp_device.dev, &dev_attr_mblog);
}
--- /dev/null
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_DSP_OMAP1_DSP_H
+#define __OMAP_DSP_OMAP1_DSP_H
+
+#ifdef CONFIG_ARCH_OMAP15XX
+#define OMAP1510_DARAM_BASE (OMAP1510_DSP_BASE + 0x0)
+#define OMAP1510_DARAM_SIZE 0x10000
+#define OMAP1510_SARAM_BASE (OMAP1510_DSP_BASE + 0x10000)
+#define OMAP1510_SARAM_SIZE 0x18000
+#endif
+
+#ifdef CONFIG_ARCH_OMAP16XX
+#define OMAP16XX_DARAM_BASE (OMAP16XX_DSP_BASE + 0x0)
+#define OMAP16XX_DARAM_SIZE 0x10000
+#define OMAP16XX_SARAM_BASE (OMAP16XX_DSP_BASE + 0x10000)
+#define OMAP16XX_SARAM_SIZE 0x18000
+#endif
+
+/*
+ * Reset Control
+ */
+#define ARM_RSTCT1_SW_RST 0x0008
+#define ARM_RSTCT1_DSP_RST 0x0004
+#define ARM_RSTCT1_DSP_EN 0x0002
+#define ARM_RSTCT1_ARM_RST 0x0001
+
+/*
+ * MPUI
+ */
+#define MPUI_CTRL_WORDSWAP_MASK 0x00600000
+#define MPUI_CTRL_WORDSWAP_ALL 0x00000000
+#define MPUI_CTRL_WORDSWAP_NONAPI 0x00200000
+#define MPUI_CTRL_WORDSWAP_API 0x00400000
+#define MPUI_CTRL_WORDSWAP_NONE 0x00600000
+#define MPUI_CTRL_AP_MASK 0x001c0000
+#define MPUI_CTRL_AP_MDH 0x00000000
+#define MPUI_CTRL_AP_MHD 0x00040000
+#define MPUI_CTRL_AP_DMH 0x00080000
+#define MPUI_CTRL_AP_HMD 0x000c0000
+#define MPUI_CTRL_AP_DHM 0x00100000
+#define MPUI_CTRL_AP_HDM 0x00140000
+#define MPUI_CTRL_BYTESWAP_MASK 0x00030000
+#define MPUI_CTRL_BYTESWAP_NONE 0x00000000
+#define MPUI_CTRL_BYTESWAP_NONAPI 0x00010000
+#define MPUI_CTRL_BYTESWAP_ALL 0x00020000
+#define MPUI_CTRL_BYTESWAP_API 0x00030000
+#define MPUI_CTRL_TIMEOUT_MASK 0x0000ff00
+#define MPUI_CTRL_APIF_HNSTB_DIV_MASK 0x000000f0
+#define MPUI_CTRL_S_NABORT_GL 0x00000008
+#define MPUI_CTRL_S_NABORT_32BIT 0x00000004
+#define MPUI_CTRL_EN_TIMEOUT 0x00000002
+#define MPUI_CTRL_HF_MCUCLK 0x00000001
+#define DSP_BOOT_CONFIG_DIRECT 0x00000000
+#define DSP_BOOT_CONFIG_PSD_DIRECT 0x00000001
+#define DSP_BOOT_CONFIG_IDLE 0x00000002
+#define DSP_BOOT_CONFIG_DL16 0x00000003
+#define DSP_BOOT_CONFIG_DL32 0x00000004
+#define DSP_BOOT_CONFIG_MPUI 0x00000005
+#define DSP_BOOT_CONFIG_INTERNAL 0x00000006
+
+/*
+ * DSP boot mode
+ * direct: 0xffff00
+ * pseudo direct: 0x080000
+ * MPUI: branch 0x010000
+ * internel: branch 0x024000
+ */
+#define DSP_BOOT_ADR_DIRECT 0xffff00
+#define DSP_BOOT_ADR_PSD_DIRECT 0x080000
+#define DSP_BOOT_ADR_MPUI 0x010000
+#define DSP_BOOT_ADR_INTERNAL 0x024000
+
+/*
+ * TC
+ */
+#define TC_ENDIANISM_SWAP 0x00000002
+#define TC_ENDIANISM_SWAP_WORD 0x00000002
+#define TC_ENDIANISM_SWAP_BYTE 0x00000000
+#define TC_ENDIANISM_EN 0x00000001
+
+/*
+ * DSP MMU
+ */
+#define DSP_MMU_BASE (0xfffed200)
+#define DSP_MMU_PREFETCH (DSP_MMU_BASE + 0x00)
+#define DSP_MMU_WALKING_ST (DSP_MMU_BASE + 0x04)
+#define DSP_MMU_CNTL (DSP_MMU_BASE + 0x08)
+#define DSP_MMU_FAULT_AD_H (DSP_MMU_BASE + 0x0c)
+#define DSP_MMU_FAULT_AD_L (DSP_MMU_BASE + 0x10)
+#define DSP_MMU_FAULT_ST (DSP_MMU_BASE + 0x14)
+#define DSP_MMU_IT_ACK (DSP_MMU_BASE + 0x18)
+#define DSP_MMU_TTB_H (DSP_MMU_BASE + 0x1c)
+#define DSP_MMU_TTB_L (DSP_MMU_BASE + 0x20)
+#define DSP_MMU_LOCK (DSP_MMU_BASE + 0x24)
+#define DSP_MMU_LD_TLB (DSP_MMU_BASE + 0x28)
+#define DSP_MMU_CAM_H (DSP_MMU_BASE + 0x2c)
+#define DSP_MMU_CAM_L (DSP_MMU_BASE + 0x30)
+#define DSP_MMU_RAM_H (DSP_MMU_BASE + 0x34)
+#define DSP_MMU_RAM_L (DSP_MMU_BASE + 0x38)
+#define DSP_MMU_GFLUSH (DSP_MMU_BASE + 0x3c)
+#define DSP_MMU_FLUSH_ENTRY (DSP_MMU_BASE + 0x40)
+#define DSP_MMU_READ_CAM_H (DSP_MMU_BASE + 0x44)
+#define DSP_MMU_READ_CAM_L (DSP_MMU_BASE + 0x48)
+#define DSP_MMU_READ_RAM_H (DSP_MMU_BASE + 0x4c)
+#define DSP_MMU_READ_RAM_L (DSP_MMU_BASE + 0x50)
+
+#define DSP_MMU_CNTL_BURST_16MNGT_EN 0x0020
+#define DSP_MMU_CNTL_WTL_EN 0x0004
+#define DSP_MMU_CNTL_MMU_EN 0x0002
+#define DSP_MMU_CNTL_RESET_SW 0x0001
+
+#define DSP_MMU_FAULT_AD_H_DP 0x0100
+#define DSP_MMU_FAULT_AD_H_ADR_MASK 0x00ff
+
+#define DSP_MMU_FAULT_ST_PREF 0x0008
+#define DSP_MMU_FAULT_ST_PERM 0x0004
+#define DSP_MMU_FAULT_ST_TLB_MISS 0x0002
+#define DSP_MMU_FAULT_ST_TRANS 0x0001
+
+#define DSP_MMU_IT_ACK_IT_ACK 0x0001
+
+#define DSP_MMU_LOCK_BASE_MASK 0xfc00
+#define DSP_MMU_LOCK_BASE_SHIFT 10
+#define DSP_MMU_LOCK_VICTIM_MASK 0x03f0
+#define DSP_MMU_LOCK_VICTIM_SHIFT 4
+
+#define DSP_MMU_CAM_H_VA_TAG_H_MASK 0x0003
+
+#define DSP_MMU_CAM_L_VA_TAG_L1_MASK 0xc000
+#define DSP_MMU_CAM_L_VA_TAG_L2_MASK_1MB 0x0000
+#define DSP_MMU_CAM_L_VA_TAG_L2_MASK_64KB 0x3c00
+#define DSP_MMU_CAM_L_VA_TAG_L2_MASK_4KB 0x3fc0
+#define DSP_MMU_CAM_L_VA_TAG_L2_MASK_1KB 0x3ff0
+#define DSP_MMU_CAM_L_P 0x0008
+#define DSP_MMU_CAM_L_V 0x0004
+#define DSP_MMU_CAM_L_PAGESIZE_MASK 0x0003
+#define DSP_MMU_CAM_L_PAGESIZE_1MB 0x0000
+#define DSP_MMU_CAM_L_PAGESIZE_64KB 0x0001
+#define DSP_MMU_CAM_L_PAGESIZE_4KB 0x0002
+#define DSP_MMU_CAM_L_PAGESIZE_1KB 0x0003
+
+#define DSP_MMU_RAM_L_RAM_LSB_MASK 0xfc00
+#define DSP_MMU_RAM_L_AP_MASK 0x0300
+#define DSP_MMU_RAM_L_AP_NA 0x0000
+#define DSP_MMU_RAM_L_AP_RO 0x0200
+#define DSP_MMU_RAM_L_AP_FA 0x0300
+
+#define DSP_MMU_GFLUSH_GFLUSH 0x0001
+
+#define DSP_MMU_FLUSH_ENTRY_FLUSH_ENTRY 0x0001
+
+#define DSP_MMU_LD_TLB_RD 0x0002
+#define DSP_MMU_LD_TLB_LD 0x0001
+
+/*
+ * DSP ICR
+ */
+#define DSPREG_ICR_RESERVED_BITS 0xffc0
+#define DSPREG_ICR_EMIF 0x0020
+#define DSPREG_ICR_DPLL 0x0010
+#define DSPREG_ICR_PER 0x0008
+#define DSPREG_ICR_CACHE 0x0004
+#define DSPREG_ICR_DMA 0x0002
+#define DSPREG_ICR_CPU 0x0001
+
+#endif /* __OMAP_DSP_OMAP1_DSP_H */
--- /dev/null
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_DSP_OMAP2_DSP_H
+#define __OMAP_DSP_OMAP2_DSP_H
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#define OMAP24XX_DARAM_BASE (DSP_MEM_24XX_VIRT + 0x0)
+#define OMAP24XX_DARAM_SIZE 0x10000
+#define OMAP24XX_SARAM_BASE (DSP_MEM_24XX_VIRT + 0x10000)
+#define OMAP24XX_SARAM_SIZE 0x18000
+#endif
+
+#include <asm/arch/hardware.h>
+#include "../../mach-omap2/prcm-regs.h"
+
+/*
+ * DSP IPI registers: mapped to 0xe1000000 -- use readX(), writeX()
+ */
+#define DSP_IPI_BASE DSP_IPI_24XX_VIRT
+#define DSP_IPI_REVISION (DSP_IPI_BASE + 0x00)
+#define DSP_IPI_SYSCONFIG (DSP_IPI_BASE + 0x10)
+#define DSP_IPI_INDEX (DSP_IPI_BASE + 0x40)
+#define DSP_IPI_ENTRY (DSP_IPI_BASE + 0x44)
+#define DSP_IPI_ENABLE (DSP_IPI_BASE + 0x48)
+#define DSP_IPI_IOMAP (DSP_IPI_BASE + 0x4c)
+#define DSP_IPI_DSPBOOTCONFIG (DSP_IPI_BASE + 0x50)
+
+#define DSP_IPI_ENTRY_ELMSIZEVALUE_MASK 0x00000003
+#define DSP_IPI_ENTRY_ELMSIZEVALUE_8 0x00000000
+#define DSP_IPI_ENTRY_ELMSIZEVALUE_16 0x00000001
+#define DSP_IPI_ENTRY_ELMSIZEVALUE_32 0x00000002
+
+#define DSP_BOOT_CONFIG_DIRECT 0x00000000
+#define DSP_BOOT_CONFIG_PSD_DIRECT 0x00000001
+#define DSP_BOOT_CONFIG_IDLE 0x00000002
+#define DSP_BOOT_CONFIG_DL16 0x00000003
+#define DSP_BOOT_CONFIG_DL32 0x00000004
+#define DSP_BOOT_CONFIG_API 0x00000005
+#define DSP_BOOT_CONFIG_INTERNAL 0x00000006
+
+/*
+ * DSP boot mode
+ * direct: 0xffff00
+ * pseudo direct: 0x080000
+ * API: branch 0x010000
+ * internel: branch 0x024000
+ */
+#define DSP_BOOT_ADR_DIRECT 0xffff00
+#define DSP_BOOT_ADR_PSD_DIRECT 0x080000
+#define DSP_BOOT_ADR_API 0x010000
+#define DSP_BOOT_ADR_INTERNAL 0x024000
+
+/*
+ * DSP MMU: mapped to 0xe2000000 -- use readX(), writeX()
+ */
+#define DSP_MMU_BASE DSP_MMU_24XX_VIRT
+#define DSP_MMU_REVISION (DSP_MMU_BASE + 0x00)
+#define DSP_MMU_SYSCONFIG (DSP_MMU_BASE + 0x10)
+#define DSP_MMU_SYSSTATUS (DSP_MMU_BASE + 0x14)
+#define DSP_MMU_IRQSTATUS (DSP_MMU_BASE + 0x18)
+#define DSP_MMU_IRQENABLE (DSP_MMU_BASE + 0x1c)
+#define DSP_MMU_WALKING_ST (DSP_MMU_BASE + 0x40)
+#define DSP_MMU_CNTL (DSP_MMU_BASE + 0x44)
+#define DSP_MMU_FAULT_AD (DSP_MMU_BASE + 0x48)
+#define DSP_MMU_TTB (DSP_MMU_BASE + 0x4c)
+#define DSP_MMU_LOCK (DSP_MMU_BASE + 0x50)
+#define DSP_MMU_LD_TLB (DSP_MMU_BASE + 0x54)
+#define DSP_MMU_CAM (DSP_MMU_BASE + 0x58)
+#define DSP_MMU_RAM (DSP_MMU_BASE + 0x5c)
+#define DSP_MMU_GFLUSH (DSP_MMU_BASE + 0x60)
+#define DSP_MMU_FLUSH_ENTRY (DSP_MMU_BASE + 0x64)
+#define DSP_MMU_READ_CAM (DSP_MMU_BASE + 0x68)
+#define DSP_MMU_READ_RAM (DSP_MMU_BASE + 0x6c)
+#define DSP_MMU_EMU_FAULT_AD (DSP_MMU_BASE + 0x70)
+
+#define DSP_MMU_SYSCONFIG_CLOCKACTIVITY_MASK 0x00000300
+#define DSP_MMU_SYSCONFIG_IDLEMODE_MASK 0x00000018
+#define DSP_MMU_SYSCONFIG_SOFTRESET 0x00000002
+#define DSP_MMU_SYSCONFIG_AUTOIDLE 0x00000001
+
+#define DSP_MMU_IRQ_MULTIHITFAULT 0x00000010
+#define DSP_MMU_IRQ_TABLEWALKFAULT 0x00000008
+#define DSP_MMU_IRQ_EMUMISS 0x00000004
+#define DSP_MMU_IRQ_TRANSLATIONFAULT 0x00000002
+#define DSP_MMU_IRQ_TLBMISS 0x00000001
+
+#define DSP_MMU_CNTL_EMUTLBUPDATE 0x00000008
+#define DSP_MMU_CNTL_TWLENABLE 0x00000004
+#define DSP_MMU_CNTL_MMUENABLE 0x00000002
+
+#define DSP_MMU_LOCK_BASE_MASK 0x00007c00
+#define DSP_MMU_LOCK_BASE_SHIFT 10
+#define DSP_MMU_LOCK_VICTIM_MASK 0x000001f0
+#define DSP_MMU_LOCK_VICTIM_SHIFT 4
+
+#define DSP_MMU_CAM_VATAG_MASK 0xfffff000
+#define DSP_MMU_CAM_P 0x00000008
+#define DSP_MMU_CAM_V 0x00000004
+#define DSP_MMU_CAM_PAGESIZE_MASK 0x00000003
+#define DSP_MMU_CAM_PAGESIZE_1MB 0x00000000
+#define DSP_MMU_CAM_PAGESIZE_64KB 0x00000001
+#define DSP_MMU_CAM_PAGESIZE_4KB 0x00000002
+#define DSP_MMU_CAM_PAGESIZE_16MB 0x00000003
+
+#define DSP_MMU_RAM_PADDR_MASK 0xfffff000
+#define DSP_MMU_RAM_ENDIANNESS 0x00000200
+#define DSP_MMU_RAM_ENDIANNESS_BIG 0x00000200
+#define DSP_MMU_RAM_ENDIANNESS_LITTLE 0x00000000
+#define DSP_MMU_RAM_ELEMENTSIZE_MASK 0x00000180
+#define DSP_MMU_RAM_ELEMENTSIZE_8 0x00000000
+#define DSP_MMU_RAM_ELEMENTSIZE_16 0x00000080
+#define DSP_MMU_RAM_ELEMENTSIZE_32 0x00000100
+#define DSP_MMU_RAM_ELEMENTSIZE_NONE 0x00000180
+#define DSP_MMU_RAM_MIXED 0x00000040
+
+#define DSP_MMU_GFLUSH_GFLUSH 0x00000001
+
+#define DSP_MMU_FLUSH_ENTRY_FLUSH_ENTRY 0x00000001
+
+#define DSP_MMU_LD_TLB_LD 0x00000001
+
+/*
+ * DSP ICR
+ */
+#define DSPREG_ICR_RESERVED_BITS 0xfc00
+#define DSPREG_ICR_HWA 0x0200
+#define DSPREG_ICR_IPORT 0x0100
+#define DSPREG_ICR_MPORT 0x0080
+#define DSPREG_ICR_XPORT 0x0040
+#define DSPREG_ICR_DPORT 0x0020
+#define DSPREG_ICR_DPLL 0x0010
+#define DSPREG_ICR_PER 0x0008
+#define DSPREG_ICR_CACHE 0x0004
+#define DSPREG_ICR_DMA 0x0002
+#define DSPREG_ICR_CPU 0x0001
+
+#endif /* __OMAP_DSP_OMAP2_DSP_H */
/*
- * linux/arch/arm/mach-omap/dsp/proclist.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * Linux task list handler
+ * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2004,2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2004/11/22: DSP Gateway version 3.3
*/
struct proc_list {
struct list_head list_head;
pid_t pid;
- unsigned int cnt;
+ struct file *file;
};
-static __inline__ void proc_list_add(struct list_head *list,
- struct task_struct *tsk)
+static __inline__ void proc_list_add(spinlock_t *lock, struct list_head *list,
+ struct task_struct *tsk, struct file *file)
{
- struct proc_list *pl;
struct proc_list *new;
- list_for_each_entry(pl, list, list_head) {
- if (pl->pid == tsk->pid) {
- /*
- * this process has opened DSP devices multi time
- */
- pl->cnt++;
- return;
- }
- }
-
new = kmalloc(sizeof(struct proc_list), GFP_KERNEL);
new->pid = tsk->pid;
- new->cnt = 1;
+ new->file = file;
+ spin_lock(lock);
list_add_tail(&new->list_head, list);
+ spin_unlock(lock);
}
-static __inline__ void proc_list_del(struct list_head *list,
- struct task_struct *tsk)
+static __inline__ void proc_list_del(spinlock_t *lock, struct list_head *list,
+ struct task_struct *tsk, struct file *file)
{
- struct proc_list *pl, *next;
+ struct proc_list *pl;
+ spin_lock(lock);
list_for_each_entry(pl, list, list_head) {
- if (pl->pid == tsk->pid) {
- if (--pl->cnt == 0) {
- list_del(&pl->list_head);
- kfree(pl);
- }
- return;
- }
- }
-
- /*
- * correspinding pid wasn't found in the list
- * -- this means the caller of proc_list_del is different from
- * the proc_list_add's caller. in this case, the parent is
- * cleaning up the context of a killed child.
- * let's delete exiting task from the list.
- */
- /* need to lock tasklist_lock before calling find_task_by_pid_type. */
- read_lock(&tasklist_lock);
- list_for_each_entry_safe(pl, next, list, list_head) {
- if (find_task_by_pid_type(PIDTYPE_PID, pl->pid) == NULL) {
+ if (pl->file == file) {
list_del(&pl->list_head);
kfree(pl);
+ spin_unlock(lock);
+ return;
}
}
- read_unlock(&tasklist_lock);
+
+ /* correspinding file struct isn't found in the list ??? */
+ printk(KERN_ERR "proc_list_del(): proc_list is inconsistent!\n"
+ "struct file (%p) not found\n", file);
+ printk(KERN_ERR "listing proc_list...\n");
+ list_for_each_entry(pl, list, list_head)
+ printk(KERN_ERR " pid:%d file:%p\n", pl->pid, pl->file);
+ spin_unlock(lock);
}
-static __inline__ void proc_list_flush(struct list_head *list)
+static __inline__ void proc_list_flush(spinlock_t *lock, struct list_head *list)
{
struct proc_list *pl;
+ spin_lock(lock);
while (!list_empty(list)) {
pl = list_entry(list->next, struct proc_list, list_head);
list_del(&pl->list_head);
kfree(pl);
}
+ spin_unlock(lock);
}
/*
- * linux/arch/arm/mach-omap/dsp/task.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * OMAP DSP task device driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- * mmap function by Hiroo Ishikawa <ext-hiroo.ishikawa@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/07/26: DSP Gateway version 3.3
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/mm.h>
-#include <linux/proc_fs.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/signal.h>
-#include <asm/irq.h>
-#include <asm/ioctls.h>
-#include <asm/arch/dsp.h>
+#include <asm/arch/mailbox.h>
#include "uaccess_dsp.h"
+#include "dsp_mbcmd.h"
#include "dsp.h"
#include "ipbuf.h"
#include "fifo.h"
#include "proclist.h"
+#include "ioctl.h"
#define is_aligned(adr,align) (!((adr)&((align)-1)))
/*
- * taskdev.state: device state machine
+ * devstate: task 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.
+ * FREEZED: task is attached, but reserved to be killed.
* 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")
+#define TASKDEV_ST_NOTASK 0x00000001
+#define TASKDEV_ST_ATTACHED 0x00000002
+#define TASKDEV_ST_GARBAGE 0x00000004
+#define TASKDEV_ST_INVALID 0x00000008
+#define TASKDEV_ST_ADDREQ 0x00000100
+#define TASKDEV_ST_DELREQ 0x00000200
+#define TASKDEV_ST_FREEZED 0x00000400
+#define TASKDEV_ST_ADDFAIL 0x00001000
+#define TASKDEV_ST_ADDING 0x00010000
+#define TASKDEV_ST_DELING 0x00020000
+#define TASKDEV_ST_KILLING 0x00040000
+#define TASKDEV_ST_STATE_MASK 0x7fffffff
+#define TASKDEV_ST_STALE 0x80000000
+
+struct {
+ long state;
+ char *name;
+} devstate_desc[] = {
+ { TASKDEV_ST_NOTASK, "notask" },
+ { TASKDEV_ST_ATTACHED, "attached" },
+ { TASKDEV_ST_GARBAGE, "garbage" },
+ { TASKDEV_ST_INVALID, "invalid" },
+ { TASKDEV_ST_ADDREQ, "addreq" },
+ { TASKDEV_ST_DELREQ, "delreq" },
+ { TASKDEV_ST_FREEZED, "freezed" },
+ { TASKDEV_ST_ADDFAIL, "addfail" },
+ { TASKDEV_ST_ADDING, "adding" },
+ { TASKDEV_ST_DELING, "deling" },
+ { TASKDEV_ST_KILLING, "killing" },
+};
+
+static char *devstate_name(long state) {
+ int i;
+ int max = ARRAY_SIZE(devstate_desc);
+
+ for (i = 0; i < max; i++) {
+ if (state & devstate_desc[i].state)
+ return devstate_desc[i].name;
+ }
+ return "unknown";
+}
+
+struct rcvdt_bk_struct {
+ struct ipblink link;
+ unsigned int rp;
+};
struct taskdev {
struct bus_type *bus;
struct device dev; /* Generic device interface */
long state;
- spinlock_t state_lock;
+ struct rw_semaphore state_sem;
wait_queue_head_t state_wait_q;
+ struct mutex usecount_mutex;
unsigned int usecount;
- char name[OMAP_DSP_TNM_LEN];
+ char name[TNM_LEN];
struct file_operations fops;
+ spinlock_t proc_list_lock;
struct list_head proc_list;
struct dsptask *task;
/* read stuff */
wait_queue_head_t read_wait_q;
struct mutex read_mutex;
+ union {
+ struct fifo_struct fifo; /* for active word */
+ struct rcvdt_bk_struct bk;
+ } rcvdt;
/* write stuff */
wait_queue_head_t write_wait_q;
struct mutex write_mutex;
+ spinlock_t wsz_lock;
+ size_t wsz;
- /* ioctl stuff */
- wait_queue_head_t ioctl_wait_q;
- struct mutex ioctl_mutex;
+ /* tctl stuff */
+ wait_queue_head_t tctl_wait_q;
+ struct mutex tctl_mutex;
+ int tctl_stat;
+ int tctl_ret; /* return value for tctl_show() */
/* device lock */
struct mutex lock;
#define to_taskdev(n) container_of(n, struct taskdev, dev)
-struct rcvdt_bk_struct {
- struct ipblink link;
- unsigned int rp;
- struct ipbuf_p *ipbuf_pvt_r;
-};
-
struct dsptask {
enum {
- TASK_STATE_ERR = 0,
- TASK_STATE_READY,
- TASK_STATE_CFGREQ
+ TASK_ST_ERR = 0,
+ TASK_ST_READY,
+ TASK_ST_CFGREQ
} state;
- unsigned char tid;
- char name[OMAP_DSP_TNM_LEN];
- unsigned short ttyp;
+ u8 tid;
+ char name[TNM_LEN];
+ u16 ttyp;
struct taskdev *dev;
/* read stuff */
- union {
- struct fifo_struct fifo; /* for active word */
- struct rcvdt_bk_struct bk;
- } rcvdt;
+ struct ipbuf_p *ipbuf_pvt_r;
/* write stuff */
- size_t wsz;
- spinlock_t wsz_lock;
- struct ipbuf_p *ipbuf_pvt_w; /* for private block */
-
- /* tctl stuff */
- int tctl_stat;
+ struct ipbuf_p *ipbuf_pvt_w;
/* mmap stuff */
void *map_base;
size_t map_length;
};
-#define sndtyp_acv(ttyp) ((ttyp) & OMAP_DSP_TTYP_ASND)
-#define sndtyp_psv(ttyp) (!((ttyp) & OMAP_DSP_TTYP_ASND))
-#define sndtyp_bk(ttyp) ((ttyp) & OMAP_DSP_TTYP_BKDM)
-#define sndtyp_wd(ttyp) (!((ttyp) & OMAP_DSP_TTYP_BKDM))
-#define sndtyp_pvt(ttyp) ((ttyp) & OMAP_DSP_TTYP_PVDM)
-#define sndtyp_gbl(ttyp) (!((ttyp) & OMAP_DSP_TTYP_PVDM))
-#define rcvtyp_acv(ttyp) ((ttyp) & OMAP_DSP_TTYP_ARCV)
-#define rcvtyp_psv(ttyp) (!((ttyp) & OMAP_DSP_TTYP_ARCV))
-#define rcvtyp_bk(ttyp) ((ttyp) & OMAP_DSP_TTYP_BKMD)
-#define rcvtyp_wd(ttyp) (!((ttyp) & OMAP_DSP_TTYP_BKMD))
-#define rcvtyp_pvt(ttyp) ((ttyp) & OMAP_DSP_TTYP_PVMD)
-#define rcvtyp_gbl(ttyp) (!((ttyp) & OMAP_DSP_TTYP_PVMD))
-
+#define sndtyp_acv(ttyp) ((ttyp) & TTYP_ASND)
+#define sndtyp_psv(ttyp) (!((ttyp) & TTYP_ASND))
+#define sndtyp_bk(ttyp) ((ttyp) & TTYP_BKDM)
+#define sndtyp_wd(ttyp) (!((ttyp) & TTYP_BKDM))
+#define sndtyp_pvt(ttyp) ((ttyp) & TTYP_PVDM)
+#define sndtyp_gbl(ttyp) (!((ttyp) & TTYP_PVDM))
+#define rcvtyp_acv(ttyp) ((ttyp) & TTYP_ARCV)
+#define rcvtyp_psv(ttyp) (!((ttyp) & TTYP_ARCV))
+#define rcvtyp_bk(ttyp) ((ttyp) & TTYP_BKMD)
+#define rcvtyp_wd(ttyp) (!((ttyp) & TTYP_BKMD))
+#define rcvtyp_pvt(ttyp) ((ttyp) & TTYP_PVMD)
+#define rcvtyp_gbl(ttyp) (!((ttyp) & TTYP_PVMD))
+
+static __inline__ int has_taskdev_lock(struct taskdev *dev);
static int dsp_rmdev_minor(unsigned char minor);
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 int taskdev_attach_task(struct taskdev *dev, struct dsptask *task);
+static int dsp_tdel_bh(struct taskdev *dev, u16 type);
+
+static struct bus_type dsptask_bus = {
+ .name = "dsptask",
+};
+
+static struct class *dsp_task_class;
+static DEFINE_MUTEX(devmgr_lock);
+static struct taskdev *taskdev[TASKDEV_MAX];
+static struct dsptask *dsptask[TASKDEV_MAX];
+static DEFINE_MUTEX(cfg_lock);
+static u16 cfg_cmd;
+static u8 cfg_tid;
+static DECLARE_WAIT_QUEUE_HEAD(cfg_wait_q);
+static u8 n_task; /* static task count */
+static void *heap;
+
+#define is_dynamic_task(tid) ((tid) >= n_task)
+
+#define devstate_read_lock(dev, devstate) \
+ devstate_read_lock_timeout(dev, devstate, 0)
+#define devstate_read_unlock(dev) up_read(&(dev)->state_sem)
+#define devstate_write_lock(dev, devstate) \
+ devstate_write_lock_timeout(dev, devstate, 0)
+#define devstate_write_unlock(dev) up_write(&(dev)->state_sem)
static ssize_t devname_show(struct device *d, struct device_attribute *attr,
char *buf);
static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
char *buf);
-static struct device_attribute dev_attr_devname = __ATTR_RO(devname);
-static struct device_attribute dev_attr_devstate = __ATTR_RO(devstate);
-static struct device_attribute dev_attr_proc_list = __ATTR_RO(proc_list);
-static struct device_attribute dev_attr_fifosz =
- __ATTR(fifosz, S_IWUGO | S_IRUGO, fifosz_show, fifosz_store);
-static struct device_attribute dev_attr_fifocnt = __ATTR_RO(fifocnt);
-static struct device_attribute dev_attr_taskname = __ATTR_RO(taskname);
-static struct device_attribute dev_attr_ttyp = __ATTR_RO(ttyp);
-static struct device_attribute dev_attr_ipblink = __ATTR_RO(ipblink);
-static struct device_attribute dev_attr_wsz = __ATTR_RO(wsz);
-static struct device_attribute dev_attr_mmap = __ATTR_RO(mmap);
-
-static struct bus_type dsptask_bus = {
- .name = "dsptask",
-};
-
-static struct class *dsp_task_class;
-static struct taskdev *taskdev[TASKDEV_MAX];
-static struct dsptask *dsptask[TASKDEV_MAX];
-static DEFINE_MUTEX(cfg_lock);
-static unsigned short cfg_cmd;
-static unsigned char cfg_tid;
-static DECLARE_WAIT_QUEUE_HEAD(cfg_wait_q);
-static unsigned char n_task;
-static void *heap;
+#define __ATTR_RW(_name,_mode) { \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
+ .show = _name##_show, \
+ .store = _name##_store, \
+}
-#define devstate_lock(dev, devstate) devstate_lock_timeout(dev, devstate, 0)
+static struct device_attribute dev_attr_devname = __ATTR_RO(devname);
+static struct device_attribute dev_attr_devstate = __ATTR_RO(devstate);
+static struct device_attribute dev_attr_proc_list = __ATTR_RO(proc_list);
+static struct device_attribute dev_attr_taskname = __ATTR_RO(taskname);
+static struct device_attribute dev_attr_ttyp = __ATTR_RO(ttyp);
+static struct device_attribute dev_attr_fifosz = __ATTR_RW(fifosz, 0666);
+static struct device_attribute dev_attr_fifocnt = __ATTR_RO(fifocnt);
+static struct device_attribute dev_attr_ipblink = __ATTR_RO(ipblink);
+static struct device_attribute dev_attr_wsz = __ATTR_RO(wsz);
+static struct device_attribute dev_attr_mmap = __ATTR_RO(mmap);
/*
- * devstate_lock_timeout():
- * when called with timeout > 0, dev->state can be diffeent from what you want.
+ * devstate_read_lock_timeout()
+ * devstate_write_lock_timeout():
+ * timeout != 0: dev->state can be diffeent from what you want.
+ * timeout == 0: no timeout
*/
-static int devstate_lock_timeout(struct taskdev *dev, long devstate,
- int timeout)
+static int devstate_read_lock_timeout(struct taskdev *dev, long devstate,
+ int timeout)
{
DECLARE_WAITQUEUE(wait, current);
long current_state = current->state;
int ret = 0;
- spin_lock(&dev->state_lock);
+ down_read(&dev->state_sem);
+ if (dev->state & devstate)
+ return 0;
+
add_wait_queue(&dev->state_wait_q, &wait);
- while (!(dev->state & devstate)) {
+ do {
set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock(&dev->state_lock);
+ up_read(&dev->state_sem);
if (timeout) {
if ((timeout = schedule_timeout(timeout)) == 0) {
/* timeout */
- spin_lock(&dev->state_lock);
+ down_read(&dev->state_sem);
break;
}
+ } else
+ schedule();
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ break;
}
- else
+ down_read(&dev->state_sem);
+ } while (!(dev->state & devstate));
+ remove_wait_queue(&dev->state_wait_q, &wait);
+ set_current_state(current_state);
+ return ret;
+}
+
+static int devstate_read_lock_and_test(struct taskdev *dev, long devstate)
+{
+ down_read(&dev->state_sem);
+ if (dev->state & devstate)
+ return 1; /* success */
+ /* failure */
+ up_read(&dev->state_sem);
+ return 0;
+}
+
+static int devstate_write_lock_timeout(struct taskdev *dev, long devstate,
+ int timeout)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ long current_state = current->state;
+ int ret = 0;
+
+ down_write(&dev->state_sem);
+ if (dev->state & devstate)
+ return 0;
+
+ add_wait_queue(&dev->state_wait_q, &wait);
+ do {
+ set_current_state(TASK_INTERRUPTIBLE);
+ up_write(&dev->state_sem);
+ if (timeout) {
+ if ((timeout = schedule_timeout(timeout)) == 0) {
+ /* timeout */
+ down_write(&dev->state_sem);
+ break;
+ }
+ } else
schedule();
if (signal_pending(current)) {
- ret = -ERESTARTSYS;
+ ret = -EINTR;
break;
}
- spin_lock(&dev->state_lock);
- }
+ down_write(&dev->state_sem);
+ } while (!(dev->state & devstate));
remove_wait_queue(&dev->state_wait_q, &wait);
set_current_state(current_state);
return ret;
}
-static __inline__ void devstate_unlock(struct taskdev *dev)
+static int devstate_write_lock_and_test(struct taskdev *dev, long devstate)
{
- spin_unlock(&dev->state_lock);
+ down_write(&dev->state_sem);
+ if (dev->state & devstate) /* success */
+ return 1;
+
+ /* failure */
+ up_write(&dev->state_sem);
+ return -1;
}
-static inline int taskdev_lock_interruptible(struct taskdev *dev,
- struct mutex *lock)
+static int taskdev_lock_interruptible(struct taskdev *dev, struct mutex *mutex)
{
int ret;
- if (dev->lock_pid == current->pid) {
- /* this process has lock */
- ret = mutex_lock_interruptible(lock);
- } else {
+ if (has_taskdev_lock(dev))
+ ret = mutex_lock_interruptible(mutex);
+ else {
if ((ret = mutex_lock_interruptible(&dev->lock)) != 0)
return ret;
- ret = mutex_lock_interruptible(lock);
+ ret = mutex_lock_interruptible(mutex);
mutex_unlock(&dev->lock);
}
+
return ret;
}
-static void proclist_send_sigbus(struct list_head *list)
+static int taskdev_lock_and_statelock_attached(struct taskdev *dev,
+ struct mutex *mutex)
{
- siginfo_t info;
- struct proc_list *pl;
- struct task_struct *tsk;
+ int ret;
- info.si_signo = SIGBUS;
- info.si_errno = 0;
- info.si_code = SI_KERNEL;
- info._sifields._sigfault._addr = NULL;
+ if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+ return -ENODEV;
- /* need to lock tasklist_lock before calling find_task_by_pid_type. */
- read_lock(&tasklist_lock);
- list_for_each_entry(pl, list, list_head) {
- if ((tsk = find_task_by_pid_type(PIDTYPE_PID, pl->pid)) != NULL)
- send_sig_info(SIGBUS, &info, tsk);
- }
- read_unlock(&tasklist_lock);
+ if ((ret = taskdev_lock_interruptible(dev, mutex)) != 0)
+ devstate_read_unlock(dev);
+
+ return ret;
}
-static int dsp_task_flush_buf(struct dsptask *task)
+static __inline__ void taskdev_unlock_and_stateunlock(struct taskdev *dev,
+ struct mutex *mutex)
+{
+ mutex_unlock(mutex);
+ devstate_read_unlock(dev);
+}
+
+/*
+ * taskdev_flush_buf()
+ * must be called under state_lock(ATTACHED) and dev->read_mutex.
+ */
+static int taskdev_flush_buf(struct taskdev *dev)
{
- unsigned short ttyp = task->ttyp;
+ u16 ttyp = dev->task->ttyp;
if (sndtyp_wd(ttyp)) {
/* word receiving */
- flush_fifo(&task->rcvdt.fifo);
+ flush_fifo(&dev->rcvdt.fifo);
} else {
/* block receiving */
- struct rcvdt_bk_struct *rcvdt = &task->rcvdt.bk;
-
- spin_lock(&rcvdt->link.lock);
- if (sndtyp_gbl(ttyp)) {
- /* global IPBUF */
- while (!ipblink_empty(&rcvdt->link)) {
- unsigned short bid = rcvdt->link.top;
- ipblink_del_top(&rcvdt->link, ipbuf);
- unuse_ipbuf(bid);
- }
- } else {
- /* private IPBUF */
- if (!ipblink_empty(&rcvdt->link)) {
- ipblink_del_pvt(&rcvdt->link);
- release_ipbuf_pvt(rcvdt->ipbuf_pvt_r);
- }
+ struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
+
+ if (sndtyp_gbl(ttyp))
+ ipblink_flush(&rcvdt->link);
+ else {
+ ipblink_flush_pvt(&rcvdt->link);
+ release_ipbuf_pvt(dev->task->ipbuf_pvt_r);
}
- spin_unlock(&rcvdt->link.lock);
}
return 0;
}
-static int dsp_task_set_fifosz(struct dsptask *task, unsigned long sz)
+/*
+ * taskdev_set_fifosz()
+ * must be called under dev->read_mutex.
+ */
+static int taskdev_set_fifosz(struct taskdev *dev, unsigned long sz)
{
- unsigned short ttyp = task->ttyp;
+ u16 ttyp = dev->task->ttyp;
int stat;
if (!(sndtyp_wd(ttyp) && sndtyp_acv(ttyp))) {
return -EINVAL;
}
- stat = realloc_fifo(&task->rcvdt.fifo, sz);
+ stat = realloc_fifo(&dev->rcvdt.fifo, sz);
if (stat == -EBUSY) {
printk(KERN_ERR "omapdsp: buffer is not empty!\n");
return stat;
} else if (stat < 0) {
printk(KERN_ERR
"omapdsp: unable to change receive buffer size. "
- "(%ld bytes for %s)\n", sz, task->name);
+ "(%ld bytes for %s)\n", sz, dev->name);
return stat;
}
return 0;
}
+static __inline__ int has_taskdev_lock(struct taskdev *dev)
+{
+ return (dev->lock_pid == current->pid);
+}
+
static int taskdev_lock(struct taskdev *dev)
{
if (mutex_lock_interruptible(&dev->lock))
- return -ERESTARTSYS;
+ return -EINTR;
dev->lock_pid = current->pid;
return 0;
}
static int taskdev_unlock(struct taskdev *dev)
{
- if (dev->lock_pid != current->pid) {
+ if (!has_taskdev_lock(dev)) {
printk(KERN_ERR
"omapdsp: an illegal process attempted to "
"unlock the dsptask lock!\n");
return 0;
}
-static int dsp_task_config(struct dsptask *task, unsigned char tid)
+static int dsp_task_config(struct dsptask *task, u8 tid)
{
- unsigned short ttyp;
- struct mbcmd mb;
+ u16 ttyp;
int ret;
task->tid = tid;
dsptask[tid] = task;
/* TCFG request */
- task->state = TASK_STATE_CFGREQ;
+ task->state = TASK_ST_CFGREQ;
if (mutex_lock_interruptible(&cfg_lock)) {
- ret = -ERESTARTSYS;
+ ret = -EINTR;
goto fail_out;
}
- cfg_cmd = MBCMD(TCFG);
- mbcmd_set(mb, MBCMD(TCFG), tid, 0);
- dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
+ cfg_cmd = MBX_CMD_DSP_TCFG;
+ mbcompose_send_and_wait(TCFG, tid, 0, &cfg_wait_q);
cfg_cmd = 0;
mutex_unlock(&cfg_lock);
- if (task->state != TASK_STATE_READY) {
+ if (task->state != TASK_ST_READY) {
printk(KERN_ERR "omapdsp: task %d configuration error!\n", tid);
ret = -EINVAL;
goto fail_out;
/* private buffer address check */
if (sndtyp_pvt(ttyp) &&
- (ipbuf_p_validate(task->rcvdt.bk.ipbuf_pvt_r, DIR_D2A) < 0)) {
+ (ipbuf_p_validate(task->ipbuf_pvt_r, DIR_D2A) < 0)) {
ret = -EINVAL;
goto fail_out;
}
goto fail_out;
}
- /*
- * initialization
- */
-
- /* read initialization */
- if (sndtyp_wd(ttyp)) {
- /* word */
- size_t fifosz;
-
- fifosz = sndtyp_psv(ttyp) ? 2 : /* passive */
- 32; /* active */
- if (init_fifo(&task->rcvdt.fifo, fifosz) < 0) {
- printk(KERN_ERR
- "omapdsp: unable to allocate receive buffer. "
- "(%d bytes for %s)\n", fifosz, task->name);
- ret = -ENOMEM;
- goto fail_out;
- }
- } else {
- /* block */
- INIT_IPBLINK(&task->rcvdt.bk.link);
- task->rcvdt.bk.rp = 0;
- }
-
- /* write initialization */
- spin_lock_init(&task->wsz_lock);
- task->wsz = rcvtyp_acv(ttyp) ? 0 : /* active */
- rcvtyp_wd(ttyp) ? 2 : /* passive word */
- ipbcfg.lsz*2; /* passive block */
-
return 0;
fail_out:
static void dsp_task_init(struct dsptask *task)
{
- dsp_mbsend(MBCMD(TCTL), task->tid, OMAP_DSP_MBCMD_TCTL_TINIT);
+ mbcompose_send(TCTL, task->tid, TCTL_TINIT);
}
-int dsp_task_config_all(unsigned char n)
+int dsp_task_config_all(u8 n)
{
int i, ret;
struct taskdev *devheap;
memset(taskdev, 0, sizeof(void *) * TASKDEV_MAX);
memset(dsptask, 0, sizeof(void *) * TASKDEV_MAX);
- n_task = n;
- printk(KERN_INFO "omapdsp: found %d task(s)\n", n_task);
- if (n_task == 0)
+ printk(KERN_INFO "omapdsp: found %d task(s)\n", n);
+ if (n == 0)
return 0;
/*
* reducing kmalloc!
*/
- devheapsz = sizeof(struct taskdev) * n_task;
- taskheapsz = sizeof(struct dsptask) * n_task;
- heap = kmalloc(devheapsz + taskheapsz, GFP_KERNEL);
- if (heap == NULL) {
- n_task = 0;
+ devheapsz = sizeof(struct taskdev) * n;
+ taskheapsz = sizeof(struct dsptask) * n;
+ heap = kzalloc(devheapsz + taskheapsz, GFP_KERNEL);
+ if (heap == NULL)
return -ENOMEM;
- }
- memset(heap, 0, devheapsz + taskheapsz);
devheap = heap;
taskheap = heap + devheapsz;
- for (i = 0; i < n_task; i++) {
+ n_task = n;
+ for (i = 0; i < n; i++) {
struct taskdev *dev = &devheap[i];
struct dsptask *task = &taskheap[i];
return ret;
if ((ret = taskdev_init(dev, task->name, i)) < 0)
return ret;
- taskdev_attach_task(dev, task);
+ if ((ret = taskdev_attach_task(dev, task)) < 0)
+ return ret;
dsp_task_init(task);
printk(KERN_INFO "omapdsp: taskdev %s enabled.\n", dev->name);
}
static void dsp_task_unconfig(struct dsptask *task)
{
- unsigned char tid = task->tid;
-
- preempt_disable();
- dsp_task_flush_buf(task);
- if (sndtyp_wd(task->ttyp) && (task->state == TASK_STATE_READY))
- free_fifo(&task->rcvdt.fifo);
- dsptask[tid] = NULL;
- preempt_enable();
+ dsptask[task->tid] = NULL;
}
void dsp_task_unconfig_all(void)
{
unsigned char minor;
- unsigned char tid;
+ u8 tid;
struct dsptask *task;
for (minor = 0; minor < n_task; minor++) {
.bus = &dsptask_bus,
};
-unsigned char dsp_task_count(void)
+u8 dsp_task_count(void)
{
return n_task;
}
{
struct taskdev *dev;
unsigned char minor;
+ unsigned int usecount;
for (minor = 0; minor < TASKDEV_MAX; minor++) {
dev = taskdev[minor];
if (dev == NULL)
continue;
- if (dev->usecount > 0) {
+ if ((usecount = dev->usecount) > 0) {
printk("dsp_taskmod_busy(): %s: usecount=%d\n",
- dev->name, dev->usecount);
+ dev->name, usecount);
return 1;
}
/*
- if ((dev->state & (OMAP_DSP_DEVSTATE_ADDREQ |
- OMAP_DSP_DEVSTATE_DELREQ)) {
+ if ((dev->state & (TASKDEV_ST_ADDREQ |
+ TASKDEV_ST_DELREQ)) {
*/
- if (dev->state & OMAP_DSP_DEVSTATE_ADDREQ) {
+ if (dev->state & TASKDEV_ST_ADDREQ) {
printk("dsp_taskmod_busy(): %s is in %s\n",
dev->name, devstate_name(dev->state));
return 1;
/*
* DSP task device file operations
*/
-static ssize_t dsp_task_read_wd_acv(struct file *file, char *buf, size_t count,
- loff_t *ppos)
+static ssize_t dsp_task_read_wd_acv(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
{
unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
struct taskdev *dev = taskdev[minor];
- int have_devstate_lock = 0;
int ret = 0;
if (count == 0) {
return -EINVAL;
}
- if (taskdev_lock_interruptible(dev, &dev->read_mutex))
- return -ERESTARTSYS;
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- have_devstate_lock = 1;
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
- if (fifo_empty(&dev->task->rcvdt.fifo)) {
+ if (fifo_empty(&dev->rcvdt.fifo)) {
long current_state = current->state;
DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&dev->read_wait_q, &wait);
- if (fifo_empty(&dev->task->rcvdt.fifo)) { /* last check */
- devstate_unlock(dev);
- have_devstate_lock = 0;
+ if (fifo_empty(&dev->rcvdt.fifo)) /* last check */
schedule();
- }
set_current_state(current_state);
remove_wait_queue(&dev->read_wait_q, &wait);
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
+ if (fifo_empty(&dev->rcvdt.fifo)) {
+ /* failure */
+ if (signal_pending(current))
+ ret = -EINTR;
goto up_out;
}
- if (!have_devstate_lock) {
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- have_devstate_lock = 1;
- }
- if (fifo_empty(&dev->task->rcvdt.fifo)) /* should not occur */
- goto up_out;
}
- ret = copy_to_user_fm_fifo(buf, &dev->task->rcvdt.fifo, count);
+ ret = copy_to_user_fm_fifo(buf, &dev->rcvdt.fifo, count);
up_out:
- if (have_devstate_lock)
- devstate_unlock(dev);
- mutex_unlock(&dev->read_mutex);
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
return ret;
}
-static ssize_t dsp_task_read_bk_acv(struct file *file, char *buf, size_t count,
- loff_t *ppos)
+static ssize_t dsp_task_read_bk_acv(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
{
unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
struct taskdev *dev = taskdev[minor];
- struct rcvdt_bk_struct *rcvdt;
- int have_devstate_lock = 0;
+ struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
ssize_t ret = 0;
if (count == 0) {
return -EINVAL;
}
- if (taskdev_lock_interruptible(dev, &dev->read_mutex))
- return -ERESTARTSYS;
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- have_devstate_lock = 1;
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
- if (ipblink_empty(&dev->task->rcvdt.bk.link)) {
+ if (ipblink_empty(&rcvdt->link)) {
long current_state;
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&dev->read_wait_q, &wait);
current_state = current->state;
set_current_state(TASK_INTERRUPTIBLE);
- if (ipblink_empty(&dev->task->rcvdt.bk.link)) { /* last check */
- devstate_unlock(dev);
- have_devstate_lock = 0;
+ if (ipblink_empty(&rcvdt->link)) /* last check */
schedule();
- }
set_current_state(current_state);
remove_wait_queue(&dev->read_wait_q, &wait);
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
+ if (ipblink_empty(&rcvdt->link)) {
+ /* failure */
+ if (signal_pending(current))
+ ret = -EINTR;
goto up_out;
}
- if (!have_devstate_lock) {
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- have_devstate_lock = 1;
- }
- /* signal or 0-byte send from DSP */
- if (ipblink_empty(&dev->task->rcvdt.bk.link))
- goto up_out;
}
- rcvdt = &dev->task->rcvdt.bk;
/* copy from delayed IPBUF */
if (sndtyp_pvt(dev->task->ttyp)) {
/* private */
if (!ipblink_empty(&rcvdt->link)) {
- struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r;
+ struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r;
unsigned char *base, *src;
size_t bkcnt;
if (dsp_mem_enable(ipbp) < 0) {
- ret = -ERESTARTSYS;
+ ret = -EBUSY;
goto up_out;
}
base = MKVIRT(ipbp->ah, ipbp->al);
if (dsp_address_validate(base, bkcnt,
"task %s read buffer",
dev->task->name) < 0) {
- ret = -ERESTARTSYS;
+ ret = -EINVAL;
goto pv_out1;
}
if (dsp_mem_enable(base) < 0) {
- ret = -ERESTARTSYS;
+ ret = -EBUSY;
goto pv_out1;
}
src = base + rcvdt->rp;
goto pv_out2;
}
ret = bkcnt;
- spin_lock(&rcvdt->link.lock);
ipblink_del_pvt(&rcvdt->link);
- spin_unlock(&rcvdt->link.lock);
release_ipbuf_pvt(ipbp);
rcvdt->rp = 0;
}
} else {
/* global */
if (dsp_mem_enable_ipbuf() < 0) {
- ret = -ERESTARTSYS;
+ ret = -EBUSY;
goto up_out;
}
while (!ipblink_empty(&rcvdt->link)) {
unsigned char *src;
size_t bkcnt;
- unsigned short bid = rcvdt->link.top;
- struct ipbuf *ipbp = ipbuf[bid];
+ struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top);
- src = ipbp->d + rcvdt->rp;
- bkcnt = ((unsigned long)ipbp->c) * 2 - rcvdt->rp;
+ src = ipb_h->p->d + rcvdt->rp;
+ bkcnt = ((unsigned long)ipb_h->p->c) * 2 - rcvdt->rp;
if (bkcnt > count) {
if (copy_to_user_dsp(buf, src, count)) {
ret = -EFAULT;
ret += bkcnt;
buf += bkcnt;
count -= bkcnt;
- spin_lock(&rcvdt->link.lock);
- ipblink_del_top(&rcvdt->link, ipbuf);
- spin_unlock(&rcvdt->link.lock);
- unuse_ipbuf(bid);
+ ipblink_del_top(&rcvdt->link);
+ unuse_ipbuf(ipb_h);
rcvdt->rp = 0;
}
}
}
up_out:
- if (have_devstate_lock)
- devstate_unlock(dev);
- mutex_unlock(&dev->read_mutex);
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
return ret;
}
-static ssize_t dsp_task_read_wd_psv(struct file *file, char *buf, size_t count,
- loff_t *ppos)
+static ssize_t dsp_task_read_wd_psv(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
{
unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
struct taskdev *dev = taskdev[minor];
- struct mbcmd mb;
- unsigned char tid;
int ret = 0;
if (count == 0) {
count = 2;
}
- if (taskdev_lock_interruptible(dev, &dev->read_mutex))
- return -ERESTARTSYS;
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- tid = dev->task->tid;
- devstate_unlock(dev);
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
- mbcmd_set(mb, MBCMD(WDREQ), tid, 0);
- dsp_mbcmd_send_and_wait(&mb, &dev->read_wait_q);
+ mbcompose_send_and_wait(WDREQ, dev->task->tid, 0, &dev->read_wait_q);
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
+ if (fifo_empty(&dev->rcvdt.fifo)) {
+ /* failure */
+ if (signal_pending(current))
+ ret = -EINTR;
goto up_out;
}
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- if (fifo_empty(&dev->task->rcvdt.fifo)) /* should not occur */
- goto unlock_out;
- ret = copy_to_user_fm_fifo(buf, &dev->task->rcvdt.fifo, count);
+ ret = copy_to_user_fm_fifo(buf, &dev->rcvdt.fifo, count);
-unlock_out:
- devstate_unlock(dev);
up_out:
- mutex_unlock(&dev->read_mutex);
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
return ret;
}
-static ssize_t dsp_task_read_bk_psv(struct file *file, char *buf, size_t count,
- loff_t *ppos)
+static ssize_t dsp_task_read_bk_psv(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
{
unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
struct taskdev *dev = taskdev[minor];
- struct rcvdt_bk_struct *rcvdt;
- struct mbcmd mb;
- unsigned char tid;
+ struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
int ret = 0;
if (count == 0) {
return -EINVAL;
}
- if (taskdev_lock_interruptible(dev, &dev->read_mutex))
- return -ERESTARTSYS;
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- tid = dev->task->tid;
- devstate_unlock(dev);
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
- mbcmd_set(mb, MBCMD(BKREQ), tid, count/2);
- dsp_mbcmd_send_and_wait(&mb, &dev->read_wait_q);
+ mbcompose_send_and_wait(BKREQ, dev->task->tid, count/2,
+ &dev->read_wait_q);
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
+ if (ipblink_empty(&rcvdt->link)) {
+ /* failure */
+ if (signal_pending(current))
+ ret = -EINTR;
goto up_out;
}
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- rcvdt = &dev->task->rcvdt.bk;
- /* signal or 0-byte send from DSP */
- if (ipblink_empty(&rcvdt->link))
- goto unlock_out;
/*
* We will not receive more than requested count.
*/
if (sndtyp_pvt(dev->task->ttyp)) {
/* private */
- struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r;
+ struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r;
size_t rcvcnt;
void *src;
if (dsp_mem_enable(ipbp) < 0) {
- ret = -ERESTARTSYS;
- goto unlock_out;
+ ret = -EBUSY;
+ goto up_out;
}
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;
+ ret = -EINVAL;
goto pv_out1;
}
if (dsp_mem_enable(src) < 0) {
- ret = -ERESTARTSYS;
+ ret = -EBUSY;
goto pv_out1;
}
if (count > rcvcnt)
ret = -EFAULT;
goto pv_out2;
}
- spin_lock(&rcvdt->link.lock);
ipblink_del_pvt(&rcvdt->link);
- spin_unlock(&rcvdt->link.lock);
release_ipbuf_pvt(ipbp);
ret = count;
pv_out2:
dsp_mem_disable(ipbp);
} else {
/* global */
- unsigned short bid = rcvdt->link.top;
- struct ipbuf *ipbp = ipbuf[bid];
+ struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top);
size_t rcvcnt;
if (dsp_mem_enable_ipbuf() < 0) {
- ret = -ERESTARTSYS;
- goto unlock_out;
+ ret = -EBUSY;
+ goto up_out;
}
- rcvcnt = ((unsigned long)ipbp->c) * 2;
+ rcvcnt = ((unsigned long)ipb_h->p->c) * 2;
if (count > rcvcnt)
count = rcvcnt;
- if (copy_to_user_dsp(buf, ipbp->d, count)) {
+ if (copy_to_user_dsp(buf, ipb_h->p->d, count)) {
ret = -EFAULT;
goto gb_out;
}
- spin_lock(&rcvdt->link.lock);
- ipblink_del_top(&rcvdt->link, ipbuf);
- spin_unlock(&rcvdt->link.lock);
- unuse_ipbuf(bid);
+ ipblink_del_top(&rcvdt->link);
+ unuse_ipbuf(ipb_h);
ret = count;
gb_out:
dsp_mem_disable_ipbuf();
}
-unlock_out:
- devstate_unlock(dev);
up_out:
- mutex_unlock(&dev->read_mutex);
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
return ret;
}
-static ssize_t dsp_task_write_wd(struct file *file, const char *buf,
+static ssize_t dsp_task_write_wd(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
struct taskdev *dev = taskdev[minor];
- unsigned short wd;
- int have_devstate_lock = 0;
+ u16 wd;
int ret = 0;
if (count == 0) {
count = 2;
}
- if (taskdev_lock_interruptible(dev, &dev->write_mutex))
- return -ERESTARTSYS;
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- have_devstate_lock = 1;
+ if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex))
+ return -ENODEV;
- if (dev->task->wsz == 0) {
+ if (dev->wsz == 0) {
long current_state;
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&dev->write_wait_q, &wait);
current_state = current->state;
set_current_state(TASK_INTERRUPTIBLE);
- if (dev->task->wsz == 0) { /* last check */
- devstate_unlock(dev);
- have_devstate_lock = 0;
+ if (dev->wsz == 0) /* last check */
schedule();
- }
set_current_state(current_state);
remove_wait_queue(&dev->write_wait_q, &wait);
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
+ if (dev->wsz == 0) {
+ /* failure */
+ if (signal_pending(current))
+ ret = -EINTR;
goto up_out;
}
- if (!have_devstate_lock) {
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- have_devstate_lock = 1;
- }
- if (dev->task->wsz == 0) /* should not occur */
- goto up_out;
}
if (copy_from_user(&wd, buf, count)) {
goto up_out;
}
- spin_lock(&dev->task->wsz_lock);
- if (dsp_mbsend(MBCMD(WDSND), dev->task->tid, wd) < 0) {
- spin_unlock(&dev->task->wsz_lock);
+ spin_lock(&dev->wsz_lock);
+ if (mbcompose_send(WDSND, dev->task->tid, wd) < 0) {
+ spin_unlock(&dev->wsz_lock);
goto up_out;
}
ret = count;
if (rcvtyp_acv(dev->task->ttyp))
- dev->task->wsz = 0;
- spin_unlock(&dev->task->wsz_lock);
+ dev->wsz = 0;
+ spin_unlock(&dev->wsz_lock);
up_out:
- if (have_devstate_lock)
- devstate_unlock(dev);
- mutex_unlock(&dev->write_mutex);
+ taskdev_unlock_and_stateunlock(dev, &dev->write_mutex);
return ret;
}
-static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
+static ssize_t dsp_task_write_bk(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
struct taskdev *dev = taskdev[minor];
- int have_devstate_lock = 0;
int ret = 0;
if (count == 0) {
return -EINVAL;
}
- if (taskdev_lock_interruptible(dev, &dev->write_mutex))
- return -ERESTARTSYS;
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- have_devstate_lock = 1;
+ if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex))
+ return -ENODEV;
- if (dev->task->wsz == 0) {
+ if (dev->wsz == 0) {
long current_state;
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&dev->write_wait_q, &wait);
current_state = current->state;
set_current_state(TASK_INTERRUPTIBLE);
- if (dev->task->wsz == 0) { /* last check */
- devstate_unlock(dev);
- have_devstate_lock = 0;
+ if (dev->wsz == 0) /* last check */
schedule();
- }
set_current_state(current_state);
remove_wait_queue(&dev->write_wait_q, &wait);
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
+ if (dev->wsz == 0) {
+ /* failure */
+ if (signal_pending(current))
+ ret = -EINTR;
goto up_out;
}
- if (!have_devstate_lock) {
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- have_devstate_lock = 1;
- }
- if (dev->task->wsz == 0) /* should not occur */
- goto up_out;
}
- if (count > dev->task->wsz)
- count = dev->task->wsz;
+ if (count > dev->wsz)
+ count = dev->wsz;
if (rcvtyp_pvt(dev->task->ttyp)) {
/* private */
unsigned char *dst;
if (dsp_mem_enable(ipbp) < 0) {
- ret = -ERESTARTSYS;
+ ret = -EBUSY;
goto up_out;
}
dst = MKVIRT(ipbp->ah, ipbp->al);
if (dsp_address_validate(dst, count, "task %s write buffer",
dev->task->name) < 0) {
- ret = -ERESTARTSYS;
+ ret = -EINVAL;
goto pv_out1;
}
if (dsp_mem_enable(dst) < 0) {
- ret = -ERESTARTSYS;
+ ret = -EBUSY;
goto pv_out1;
}
if (copy_from_user_dsp(dst, buf, count)) {
}
ipbp->c = count/2;
ipbp->s = dev->task->tid;
- spin_lock(&dev->task->wsz_lock);
- if (dsp_mbsend(MBCMD(BKSNDP), dev->task->tid, 0) == 0) {
+ spin_lock(&dev->wsz_lock);
+ if (mbcompose_send(BKSNDP, dev->task->tid, 0) == 0) {
if (rcvtyp_acv(dev->task->ttyp))
- dev->task->wsz = 0;
+ dev->wsz = 0;
ret = count;
}
- spin_unlock(&dev->task->wsz_lock);
+ spin_unlock(&dev->wsz_lock);
pv_out2:
dsp_mem_disable(dst);
pv_out1:
dsp_mem_disable(ipbp);
} else {
/* global */
- struct ipbuf *ipbp;
- unsigned short bid;
+ struct ipbuf_head *ipb_h;
if (dsp_mem_enable_ipbuf() < 0) {
- ret = -ERESTARTSYS;
+ ret = -EBUSY;
goto up_out;
}
- bid = get_free_ipbuf(dev->task->tid);
- if (bid == OMAP_DSP_BID_NULL)
+ if ((ipb_h = get_free_ipbuf(dev->task->tid)) == NULL)
goto gb_out;
- ipbp = ipbuf[bid];
- if (copy_from_user_dsp(ipbp->d, buf, count)) {
- release_ipbuf(bid);
+ if (copy_from_user_dsp(ipb_h->p->d, buf, count)) {
+ release_ipbuf(ipb_h);
ret = -EFAULT;
goto gb_out;
}
- ipbp->c = count/2;
- ipbp->sa = dev->task->tid;
- spin_lock(&dev->task->wsz_lock);
- if (dsp_mbsend(MBCMD(BKSND), dev->task->tid, bid) == 0) {
+ ipb_h->p->c = count/2;
+ ipb_h->p->sa = dev->task->tid;
+ spin_lock(&dev->wsz_lock);
+ if (mbcompose_send(BKSND, dev->task->tid, ipb_h->bid) == 0) {
if (rcvtyp_acv(dev->task->ttyp))
- dev->task->wsz = 0;
+ dev->wsz = 0;
ret = count;
ipb_bsycnt_inc(&ipbcfg);
} else
- release_ipbuf(bid);
- spin_unlock(&dev->task->wsz_lock);
+ release_ipbuf(ipb_h);
+ spin_unlock(&dev->wsz_lock);
gb_out:
dsp_mem_disable_ipbuf();
}
up_out:
- if (have_devstate_lock)
- devstate_unlock(dev);
- mutex_unlock(&dev->write_mutex);
+ taskdev_unlock_and_stateunlock(dev, &dev->write_mutex);
return ret;
}
struct dsptask *task = dev->task;
unsigned int mask = 0;
+ if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+ return 0;
poll_wait(file, &dev->read_wait_q, wait);
poll_wait(file, &dev->write_wait_q, wait);
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0)
- return 0;
if (sndtyp_psv(task->ttyp) ||
- (sndtyp_wd(task->ttyp) && !fifo_empty(&task->rcvdt.fifo)) ||
- (sndtyp_bk(task->ttyp) && !ipblink_empty(&task->rcvdt.bk.link)))
+ (sndtyp_wd(task->ttyp) && !fifo_empty(&dev->rcvdt.fifo)) ||
+ (sndtyp_bk(task->ttyp) && !ipblink_empty(&dev->rcvdt.bk.link)))
mask |= POLLIN | POLLRDNORM;
- if (task->wsz)
+ if (dev->wsz)
mask |= POLLOUT | POLLWRNORM;
- devstate_unlock(dev);
+ devstate_read_unlock(dev);
return mask;
}
-static int dsp_task_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int dsp_tctl_issue(struct taskdev *dev, u16 cmd, int argc, u16 argv[])
{
- unsigned int minor = MINOR(inode->i_rdev);
- struct taskdev *dev = taskdev[minor];
- struct mbcmd mb;
- unsigned char tid;
+ int tctl_argc;
struct mb_exarg mbarg, *mbargp;
- int mbargc;
- unsigned short mbargv[1];
int interactive;
- int ret;
-
- /* LOCK / UNLOCK operations */
- switch (cmd) {
- case OMAP_DSP_TASK_IOCTL_LOCK:
- return taskdev_lock(dev);
- case OMAP_DSP_TASK_IOCTL_UNLOCK:
- return taskdev_unlock(dev);
- }
-
- /*
- * actually only interractive commands need to lock
- * the mutex, but here all commands do it for simplicity.
- */
- if (taskdev_lock_interruptible(dev, &dev->ioctl_mutex))
- return -ERESTARTSYS;
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
+ u8 tid;
+ int ret = 0;
- if ((cmd >= 0x0080) && (cmd < 0x0100)) {
- /*
- * 0x0080 - 0x00ff
- * 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) {
+ if (cmd < 0x8000) {
/*
- * 0x0000 - 0x7fff (except 0x0080 - 0x00ff)
+ * 0x0000 - 0x7fff
* system reserved TCTL commands
*/
switch (cmd) {
- case OMAP_DSP_MBCMD_TCTL_TEN:
- case OMAP_DSP_MBCMD_TCTL_TDIS:
- mbargc = 0;
+ case TCTL_TEN:
+ case TCTL_TDIS:
+ tctl_argc = 0;
interactive = 0;
break;
default:
- ret = -ENOIOCTLCMD;
- goto unlock_out;
+ return -EINVAL;
}
}
/*
*/
else if (cmd < 0x8100) {
/* 0x8000-0x80ff: no arg, non-interactive */
- mbargc = 0;
+ tctl_argc = 0;
interactive = 0;
} else if (cmd < 0x8200) {
/* 0x8100-0x81ff: 1 arg, non-interactive */
- mbargc = 1;
- mbargv[0] = arg & 0xffff;
+ tctl_argc = 1;
interactive = 0;
} else if (cmd < 0x9000) {
/* 0x8200-0x8fff: reserved */
- ret = -ENOIOCTLCMD;
- goto unlock_out;
+ return -EINVAL;
} else if (cmd < 0x9100) {
/* 0x9000-0x90ff: no arg, interactive */
- mbargc = 0;
+ tctl_argc = 0;
interactive = 1;
} else if (cmd < 0x9200) {
/* 0x9100-0x91ff: 1 arg, interactive */
- mbargc = 1;
- mbargv[0] = arg & 0xffff;
+ tctl_argc = 1;
interactive = 1;
- } else if (cmd < 0x10000) {
- /* 0x9200-0xffff: reserved */
- ret = -ENOIOCTLCMD;
- goto unlock_out;
} else {
- /*
- * 0x10000 -
- * non TCTL ioctls
- */
- switch (cmd) {
- case OMAP_DSP_TASK_IOCTL_BFLSH:
- ret = dsp_task_flush_buf(dev->task);
- break;
- case OMAP_DSP_TASK_IOCTL_SETBSZ:
- ret = dsp_task_set_fifosz(dev->task, arg);
- break;
- case OMAP_DSP_TASK_IOCTL_GETNAME:
- ret = 0;
- if (copy_to_user((void *)arg, dev->name,
- strlen(dev->name) + 1))
- ret = -EFAULT;
- break;
- default:
- ret = -ENOIOCTLCMD;
- }
- goto unlock_out;
+ /* 0x9200-0xffff: reserved */
+ return -EINVAL;
}
+ /*
+ * if argc < 0, use tctl_argc as is.
+ * if argc >= 0, check arg count.
+ */
+ if ((argc >= 0) && (argc != tctl_argc))
+ return -EINVAL;
+
/*
* issue TCTL
*/
+ if (taskdev_lock_interruptible(dev, &dev->tctl_mutex))
+ return -EINTR;
+
tid = dev->task->tid;
- mbcmd_set(mb, MBCMD(TCTL), tid, cmd);
- if (mbargc > 0) {
- mbarg.argc = mbargc;
+ if (tctl_argc > 0) {
+ mbarg.argc = tctl_argc;
mbarg.tid = tid;
- mbarg.argv = mbargv;
+ mbarg.argv = argv;
mbargp = &mbarg;
} else
mbargp = NULL;
if (interactive) {
- dev->task->tctl_stat = -ERESTARTSYS;
- devstate_unlock(dev);
+ dev->tctl_stat = -EINVAL;
- dsp_mbcmd_send_and_wait_exarg(&mb, mbargp, &dev->ioctl_wait_q);
+ mbcompose_send_and_wait_exarg(TCTL, tid, cmd, mbargp,
+ &dev->tctl_wait_q);
if (signal_pending(current)) {
- ret = -ERESTARTSYS;
+ ret = -EINTR;
goto up_out;
}
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
- ret = -ERESTARTSYS;
- goto up_out;
- }
- ret = dev->task->tctl_stat;
- if (ret < 0) {
+ if ((ret = dev->tctl_stat) < 0) {
printk(KERN_ERR "omapdsp: TCTL not responding.\n");
- goto unlock_out;
+ goto up_out;
}
- } else {
- dsp_mbcmd_send_exarg(&mb, mbargp);
+ } else
+ mbcompose_send_exarg(TCTL, tid, cmd, mbargp);
+
+up_out:
+ mutex_unlock(&dev->tctl_mutex);
+ return ret;
+}
+
+static int dsp_task_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ unsigned int minor = MINOR(inode->i_rdev);
+ struct taskdev *dev = taskdev[minor];
+ int ret;
+
+ if (cmd < 0x10000) {
+ /* issue TCTL */
+ u16 mbargv[1];
+
+ mbargv[0] = arg & 0xffff;
+ return dsp_tctl_issue(dev, cmd, -1, mbargv);
+ }
+
+ /* non TCTL ioctls */
+ switch (cmd) {
+
+ case TASK_IOCTL_LOCK:
+ ret = taskdev_lock(dev);
+ break;
+
+ case TASK_IOCTL_UNLOCK:
+ ret = taskdev_unlock(dev);
+ break;
+
+ case TASK_IOCTL_BFLSH:
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
+ ret = taskdev_flush_buf(dev);
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
+ break;
+
+ case TASK_IOCTL_SETBSZ:
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
+ ret = taskdev_set_fifosz(dev, arg);
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
+ break;
+
+ case TASK_IOCTL_GETNAME:
ret = 0;
+ if (copy_to_user((void __user *)arg, dev->name,
+ strlen(dev->name) + 1))
+ ret = -EFAULT;
+ break;
+
+ default:
+ ret = -ENOIOCTLCMD;
+
}
-unlock_out:
- devstate_unlock(dev);
-up_out:
- mutex_unlock(&dev->ioctl_mutex);
return ret;
}
struct dsptask *task;
size_t len = vma->vm_end - vma->vm_start;
- BUG_ON(!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED));
+ BUG_ON(!(dev->state & TASKDEV_ST_ATTACHED));
task = dev->task;
exmap_use(task->map_base, len);
}
struct dsptask *task;
size_t len = vma->vm_end - vma->vm_start;
- BUG_ON(!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED));
+ BUG_ON(!(dev->state & TASKDEV_ST_ATTACHED));
task = dev->task;
exmap_unuse(task->map_base, len);
}
struct dsptask *task;
int ret = 0;
- if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0)
- return -ERESTARTSYS;
+ if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+ return -ENODEV;
task = dev->task;
/*
exmap_use(task->map_base, vma->vm_end - vma->vm_start);
unlock_out:
- devstate_unlock(dev);
+ devstate_read_unlock(dev);
return ret;
}
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;
-#ifndef CONFIG_OMAP_DSP_TASK_MULTIOPEN
- if (dev->usecount > 0) {
- ret = -EBUSY;
- goto unlock_out;
- }
-#endif
- 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) {
- 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) {
- printk(KERN_ERR "omapdsp: task attach failed for %s!\n",
- dev->name);
- ret = -EBUSY;
- dev->state = OMAP_DSP_DEVSTATE_NOTASK;
- wake_up_interruptible_all(&dev->state_wait_q);
- goto unlock_out;
+restart:
+ mutex_lock(&dev->usecount_mutex);
+ down_write(&dev->state_sem);
+
+ /* state can be NOTASK, ATTACHED/FREEZED, KILLING, GARBAGE or INVALID here. */
+ switch (dev->state & TASKDEV_ST_STATE_MASK) {
+ case TASKDEV_ST_NOTASK:
+ break;
+ case TASKDEV_ST_ATTACHED:
+ goto attached;
+
+ case TASKDEV_ST_INVALID:
+ up_write(&dev->state_sem);
+ mutex_unlock(&dev->usecount_mutex);
+ return -ENODEV;
+
+ case TASKDEV_ST_FREEZED:
+ case TASKDEV_ST_KILLING:
+ case TASKDEV_ST_GARBAGE:
+ /* on the kill process. wait until it becomes NOTASK. */
+ up_write(&dev->state_sem);
+ mutex_unlock(&dev->usecount_mutex);
+ if (devstate_write_lock(dev, TASKDEV_ST_NOTASK) < 0)
+ return -EINTR;
+ devstate_write_unlock(dev);
+ goto restart;
+ }
+
+ /* NOTASK */
+ dev->state = TASKDEV_ST_ADDREQ;
+ /* wake up twch daemon for tadd */
+ dsp_twch_touch();
+ up_write(&dev->state_sem);
+ if (devstate_write_lock(dev, TASKDEV_ST_ATTACHED |
+ TASKDEV_ST_ADDFAIL) < 0) {
+ /* cancelled */
+ if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) {
+ mutex_unlock(&dev->usecount_mutex);
+ /* out of control ??? */
+ return -EINTR;
}
+ dev->state = TASKDEV_ST_NOTASK;
+ ret = -EINTR;
+ goto change_out;
+ }
+ if (dev->state & TASKDEV_ST_ADDFAIL) {
+ printk(KERN_ERR "omapdsp: task attach failed for %s!\n",
+ dev->name);
+ ret = -EBUSY;
+ dev->state = TASKDEV_ST_NOTASK;
+ goto change_out;
}
- /* state_lock covers usecount, proc_list as well. */
+attached:
+ /* ATTACHED */
+#ifndef CONFIG_OMAP_DSP_TASK_MULTIOPEN
+ if (dev->usecount > 0) {
+ up_write(&dev->state_sem);
+ return -EBUSY;
+ }
+#endif
dev->usecount++;
- proc_list_add(&dev->proc_list, current);
+ proc_list_add(&dev->proc_list_lock, &dev->proc_list, current, file);
file->f_op = &dev->fops;
- devstate_unlock(dev);
+ up_write(&dev->state_sem);
+ mutex_unlock(&dev->usecount_mutex);
+#ifdef DSP_PTE_FREE /* not used currently. */
+ dsp_map_update(current);
+ dsp_cur_users_add(current);
+#endif /* DSP_PTE_FREE */
return 0;
-unlock_out:
- devstate_unlock(dev);
+change_out:
+ wake_up_interruptible_all(&dev->state_wait_q);
+ up_write(&dev->state_sem);
+ mutex_unlock(&dev->usecount_mutex);
return ret;
}
unsigned int minor = MINOR(inode->i_rdev);
struct taskdev *dev = taskdev[minor];
- /* state_lock covers usecount, proc_list as well. */
- spin_lock(&dev->state_lock);
+#ifdef DSP_PTE_FREE /* not used currently. */
+ dsp_cur_users_del(current);
+#endif /* DSP_PTE_FREE */
+
+ if (has_taskdev_lock(dev))
+ taskdev_unlock(dev);
+
+ proc_list_del(&dev->proc_list_lock, &dev->proc_list, current, file);
+ mutex_lock(&dev->usecount_mutex);
+ if (--dev->usecount > 0) {
+ /* other processes are using this device. no state change. */
+ mutex_unlock(&dev->usecount_mutex);
+ return 0;
+ }
+
+ /* usecount == 0 */
+ down_write(&dev->state_sem);
- /* state can be ATTACHED, KILLING or GARBAGE here. */
- switch (dev->state & OMAP_DSP_DEVSTATE_STATE_MASK) {
+ /* state can be ATTACHED/FREEZED, KILLING or GARBAGE here. */
+ switch (dev->state & TASKDEV_ST_STATE_MASK) {
- case OMAP_DSP_DEVSTATE_KILLING:
- dev->usecount--;
+ case TASKDEV_ST_KILLING:
break;
- case OMAP_DSP_DEVSTATE_GARBAGE:
- if(--dev->usecount == 0) {
- dev->state = OMAP_DSP_DEVSTATE_NOTASK;
- wake_up_interruptible_all(&dev->state_wait_q);
- }
+ case TASKDEV_ST_GARBAGE:
+ dev->state = TASKDEV_ST_NOTASK;
+ wake_up_interruptible_all(&dev->state_wait_q);
break;
- case OMAP_DSP_DEVSTATE_ATTACHED:
- if (dev->lock_pid == current->pid)
- taskdev_unlock(dev);
- proc_list_del(&dev->proc_list, current);
- if (--dev->usecount == 0) {
- if (minor >= n_task) { /* dynamic task */
- dev->state = OMAP_DSP_DEVSTATE_DELREQ;
- /* wake up twch daemon for tdel */
- dsp_twch_touch();
- }
+ case TASKDEV_ST_ATTACHED:
+ case TASKDEV_ST_FREEZED:
+ if (is_dynamic_task(minor)) {
+ dev->state = TASKDEV_ST_DELREQ;
+ /* wake up twch daemon for tdel */
+ dsp_twch_touch();
}
break;
}
- spin_unlock(&dev->state_lock);
+ up_write(&dev->state_sem);
+ mutex_unlock(&dev->usecount_mutex);
return 0;
}
struct taskdev *dev;
int status;
unsigned char minor;
+ int ret;
- if (!dsp_is_ready()) {
+ if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
return -EINVAL;
}
+
+ if (mutex_lock_interruptible(&devmgr_lock))
+ return -EINTR;
+
+ /* naming check */
+ for (minor = 0; minor < TASKDEV_MAX; minor++) {
+ if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
+ printk(KERN_ERR
+ "omapdsp: task device name %s is already "
+ "in use.\n", name);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ /* find free minor number */
for (minor = n_task; minor < TASKDEV_MAX; minor++) {
if (taskdev[minor] == NULL)
goto do_make;
}
printk(KERN_ERR "omapdsp: Too many task devices.\n");
- return -EBUSY;
+ ret = -EBUSY;
+ goto out;
do_make:
- if ((dev = kmalloc(sizeof(struct taskdev), GFP_KERNEL)) == NULL)
- return -ENOMEM;
- memset(dev, 0, sizeof(struct taskdev));
+ if ((dev = kzalloc(sizeof(struct taskdev), GFP_KERNEL)) == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
if ((status = taskdev_init(dev, name, minor)) < 0) {
kfree(dev);
- return status;
+ ret = status;
+ goto out;
}
- return minor;
+ ret = minor;
+
+out:
+ mutex_unlock(&devmgr_lock);
+ return ret;
}
int dsp_rmdev(char *name)
{
unsigned char minor;
+ int status;
int ret;
- if (!dsp_is_ready()) {
+ if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
return -EINVAL;
}
+
+ if (mutex_lock_interruptible(&devmgr_lock))
+ return -EINTR;
+
+ /* find in dynamic devices */
for (minor = n_task; minor < TASKDEV_MAX; minor++) {
+ if (taskdev[minor] && !strcmp(taskdev[minor]->name, name))
+ goto do_remove;
+ }
+
+ /* find in static devices */
+ for (minor = 0; minor < n_task; minor++) {
if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
- if ((ret = dsp_rmdev_minor(minor)) < 0)
- return ret;
- return minor;
+ printk(KERN_ERR
+ "omapdsp: task device %s is static.\n", name);
+ ret = -EINVAL;
+ goto out;
}
}
+
+ printk(KERN_ERR "omapdsp: task device %s not found.\n", name);
return -EINVAL;
+
+do_remove:
+ ret = minor;
+ if ((status = dsp_rmdev_minor(minor)) < 0)
+ ret = status;
+out:
+ mutex_unlock(&devmgr_lock);
+ return ret;
}
static int dsp_rmdev_minor(unsigned char minor)
{
struct taskdev *dev = taskdev[minor];
- spin_lock(&dev->state_lock);
+ while (!down_write_trylock(&dev->state_sem)) {
+ down_read(&dev->state_sem);
+ if (dev->state & (TASKDEV_ST_ATTACHED |
+ TASKDEV_ST_FREEZED)) {
+ /*
+ * task is working. kill it.
+ * ATTACHED -> FREEZED can be changed under
+ * down_read of state_sem..
+ */
+ dev->state = TASKDEV_ST_FREEZED;
+ wake_up_interruptible_all(&dev->read_wait_q);
+ wake_up_interruptible_all(&dev->write_wait_q);
+ wake_up_interruptible_all(&dev->tctl_wait_q);
+ }
+ up_read(&dev->state_sem);
+ schedule();
+ }
- switch (dev->state & OMAP_DSP_DEVSTATE_STATE_MASK) {
+ switch (dev->state & TASKDEV_ST_STATE_MASK) {
- case OMAP_DSP_DEVSTATE_NOTASK:
+ case TASKDEV_ST_NOTASK:
/* fine */
- break;
+ goto notask;
- case OMAP_DSP_DEVSTATE_ATTACHED:
+ case TASKDEV_ST_ATTACHED:
+ case TASKDEV_ST_FREEZED:
/* task is working. kill it. */
- dev->state = OMAP_DSP_DEVSTATE_KILLING;
- proclist_send_sigbus(&dev->proc_list);
- spin_unlock(&dev->state_lock);
- dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_KILL);
+ dev->state = TASKDEV_ST_KILLING;
+ up_write(&dev->state_sem);
+ dsp_tdel_bh(dev, TDEL_KILL);
goto invalidate;
- case OMAP_DSP_DEVSTATE_ADDREQ:
+ case TASKDEV_ST_ADDREQ:
/* open() is waiting. drain it. */
- dev->state = OMAP_DSP_DEVSTATE_ADDFAIL;
+ dev->state = TASKDEV_ST_ADDFAIL;
wake_up_interruptible_all(&dev->state_wait_q);
break;
- case OMAP_DSP_DEVSTATE_DELREQ:
+ case TASKDEV_ST_DELREQ:
/* nobody is waiting. */
- dev->state = OMAP_DSP_DEVSTATE_NOTASK;
+ dev->state = TASKDEV_ST_NOTASK;
wake_up_interruptible_all(&dev->state_wait_q);
break;
- 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:
+ case TASKDEV_ST_ADDING:
+ case TASKDEV_ST_DELING:
+ case TASKDEV_ST_KILLING:
+ case TASKDEV_ST_GARBAGE:
+ case TASKDEV_ST_ADDFAIL:
/* transient state. wait for a moment. */
break;
}
- spin_unlock(&dev->state_lock);
+ up_write(&dev->state_sem);
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)) {
+ devstate_read_lock_timeout(dev, TASKDEV_ST_NOTASK, 5 * HZ);
+ if (!(dev->state & TASKDEV_ST_NOTASK)) {
printk(KERN_WARNING
"omapdsp: illegal device state (%s) on rmdev %s.\n",
devstate_name(dev->state), dev->name);
}
- dev->state = OMAP_DSP_DEVSTATE_INVALID;
- devstate_unlock(dev);
+notask:
+ dev->state = TASKDEV_ST_INVALID;
+ devstate_read_unlock(dev);
taskdev_delete(minor);
kfree(dev);
static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor)
{
- struct class_device *cdev;
-
taskdev[minor] = dev;
+ spin_lock_init(&dev->proc_list_lock);
INIT_LIST_HEAD(&dev->proc_list);
init_waitqueue_head(&dev->read_wait_q);
init_waitqueue_head(&dev->write_wait_q);
- init_waitqueue_head(&dev->ioctl_wait_q);
+ init_waitqueue_head(&dev->tctl_wait_q);
mutex_init(&dev->read_mutex);
mutex_init(&dev->write_mutex);
- mutex_init(&dev->ioctl_mutex);
+ mutex_init(&dev->tctl_mutex);
mutex_init(&dev->lock);
+ spin_lock_init(&dev->wsz_lock);
+ dev->tctl_ret = -EINVAL;
dev->lock_pid = 0;
- strncpy(dev->name, name, OMAP_DSP_TNM_LEN);
- dev->name[OMAP_DSP_TNM_LEN-1] = '\0';
- dev->state = (minor < n_task) ? OMAP_DSP_DEVSTATE_ATTACHED :
- OMAP_DSP_DEVSTATE_NOTASK;
+ strncpy(dev->name, name, TNM_LEN);
+ dev->name[TNM_LEN-1] = '\0';
+ dev->state = (minor < n_task) ? TASKDEV_ST_ATTACHED : TASKDEV_ST_NOTASK;
dev->usecount = 0;
+ mutex_init(&dev->usecount_mutex);
memcpy(&dev->fops, &dsp_task_fops, sizeof(struct file_operations));
dev->dev.parent = &dsp_device.dev;
device_create_file(&dev->dev, &dev_attr_devname);
device_create_file(&dev->dev, &dev_attr_devstate);
device_create_file(&dev->dev, &dev_attr_proc_list);
- cdev = class_device_create(dsp_task_class, NULL,
- MKDEV(OMAP_DSP_TASK_MAJOR, minor),
- NULL, "dsptask%d", minor);
+ class_device_create(dsp_task_class, NULL,
+ MKDEV(OMAP_DSP_TASK_MAJOR, minor),
+ NULL, "dsptask%d", minor);
init_waitqueue_head(&dev->state_wait_q);
- spin_lock_init(&dev->state_lock);
+ init_rwsem(&dev->state_sem);
return 0;
}
device_remove_file(&dev->dev, &dev_attr_proc_list);
class_device_destroy(dsp_task_class, MKDEV(OMAP_DSP_TASK_MAJOR, minor));
device_unregister(&dev->dev);
- proc_list_flush(&dev->proc_list);
+ proc_list_flush(&dev->proc_list_lock, &dev->proc_list);
taskdev[minor] = NULL;
}
-static void taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
+static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
{
- unsigned short ttyp = task->ttyp;
+ u16 ttyp = task->ttyp;
- dev->task = task;
- task->dev = dev;
dev->fops.read =
sndtyp_acv(ttyp) ?
sndtyp_wd(ttyp) ? dsp_task_read_wd_acv:
/* sndtyp_psv */
sndtyp_wd(ttyp) ? dsp_task_read_wd_psv:
/* sndtyp_bk */ dsp_task_read_bk_psv;
+ if (sndtyp_wd(ttyp)) {
+ /* word */
+ size_t fifosz;
+
+ fifosz = sndtyp_psv(ttyp) ? 2 : /* passive */
+ 32; /* active */
+ if (init_fifo(&dev->rcvdt.fifo, fifosz) < 0) {
+ printk(KERN_ERR
+ "omapdsp: unable to allocate receive buffer. "
+ "(%d bytes for %s)\n", fifosz, dev->name);
+ return -ENOMEM;
+ }
+ } else {
+ /* block */
+ INIT_IPBLINK(&dev->rcvdt.bk.link);
+ dev->rcvdt.bk.rp = 0;
+ }
+
dev->fops.write =
rcvtyp_wd(ttyp) ? dsp_task_write_wd:
/* rcvbyp_bk */ dsp_task_write_bk;
+ dev->wsz = rcvtyp_acv(ttyp) ? 0 : /* active */
+ rcvtyp_wd(ttyp) ? 2 : /* passive word */
+ ipbcfg.lsz*2; /* passive block */
+
if (task->map_length)
dev->fops.mmap = dsp_task_mmap;
device_create_file(&dev->dev, &dev_attr_wsz);
if (task->map_length)
device_create_file(&dev->dev, &dev_attr_mmap);
+
+ dev->task = task;
+ task->dev = dev;
+
+ return 0;
}
static void taskdev_detach_task(struct taskdev *dev)
{
- unsigned short ttyp = dev->task->ttyp;
+ u16 ttyp = dev->task->ttyp;
device_remove_file(&dev->dev, &dev_attr_taskname);
device_remove_file(&dev->dev, &dev_attr_ttyp);
if (dev->task->map_length)
device_remove_file(&dev->dev, &dev_attr_mmap);
- if (dev->task) {
- dev->task = NULL;
- dev->fops.read = NULL;
- dev->fops.write = NULL;
- printk(KERN_INFO "omapdsp: taskdev %s disabled.\n", dev->name);
- }
+ dev->fops.read = NULL;
+ taskdev_flush_buf(dev);
+ if (sndtyp_wd(ttyp))
+ free_fifo(&dev->rcvdt.fifo);
+
+ dev->fops.write = NULL;
+ dev->wsz = 0;
+
+ printk(KERN_INFO "omapdsp: taskdev %s disabled.\n", dev->name);
+ dev->task = NULL;
}
/*
* tadd / tdel / tkill
*/
-int dsp_tadd(unsigned char minor, unsigned long adr)
+static int dsp_tadd(struct taskdev *dev, dsp_long_t adr)
{
- struct taskdev *dev;
struct dsptask *task;
- struct mbcmd mb;
struct mb_exarg arg;
- unsigned char tid, tid_response;
- unsigned short argv[2];
- 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;
- }
+ u8 tid, tid_response;
+ u16 argv[2];
+ int ret = 0;
- spin_lock(&dev->state_lock);
- if (!(dev->state & OMAP_DSP_DEVSTATE_ADDREQ)) {
+ if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) {
printk(KERN_ERR
"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);
+ dev->state = TASKDEV_ST_ADDING;
+ devstate_write_unlock(dev);
- if (adr == OMAP_DSP_TADD_ABORTADR) {
+ if (adr == TADD_ABORTADR) {
/* aborting tadd intentionally */
printk(KERN_INFO "omapdsp: tadd address is ABORTADR.\n");
goto fail_out;
}
if (adr >= DSPSPACE_SIZE) {
printk(KERN_ERR
- "omapdsp: illegal address 0x%08lx for tadd\n", adr);
+ "omapdsp: illegal address 0x%08x for tadd\n", adr);
ret = -EINVAL;
goto fail_out;
}
argv[1] = adr & 0xffff; /* addrl */
if (mutex_lock_interruptible(&cfg_lock)) {
- ret = -ERESTARTSYS;
+ ret = -EINTR;
goto fail_out;
}
- cfg_tid = OMAP_DSP_TID_ANON;
- cfg_cmd = MBCMD(TADD);
- mbcmd_set(mb, MBCMD(TADD), 0, 0);
- arg.tid = OMAP_DSP_TID_ANON;
+ cfg_tid = TID_ANON;
+ cfg_cmd = MBX_CMD_DSP_TADD;
+ arg.tid = TID_ANON;
arg.argc = 2;
arg.argv = argv;
cfg_cmd = 0;
mutex_unlock(&cfg_lock);
- if (tid == OMAP_DSP_TID_ANON) {
+ if (tid == TID_ANON) {
printk(KERN_ERR "omapdsp: tadd failed!\n");
ret = -EINVAL;
goto fail_out;
ret = -EINVAL;
goto fail_out;
}
- if ((task = kmalloc(sizeof(struct dsptask), GFP_KERNEL)) == NULL) {
+ if ((task = kzalloc(sizeof(struct dsptask), GFP_KERNEL)) == NULL) {
ret = -ENOMEM;
goto del_out;
}
- memset(task, 0, sizeof(struct dsptask));
if ((ret = dsp_task_config(task, tid)) < 0)
goto free_out;
- taskdev_attach_task(dev, task);
if (strcmp(dev->name, task->name)) {
printk(KERN_ERR
goto free_out;
}
+ if ((ret = taskdev_attach_task(dev, task)) < 0)
+ goto free_out;
+
dsp_task_init(task);
printk(KERN_INFO "omapdsp: taskdev %s enabled.\n", dev->name);
- dev->state = OMAP_DSP_DEVSTATE_ATTACHED;
+ dev->state = TASKDEV_ST_ATTACHED;
wake_up_interruptible_all(&dev->state_wait_q);
- return minor;
+ return 0;
free_out:
kfree(task);
del_out:
printk(KERN_ERR "omapdsp: deleting the task...\n");
- dev->state = OMAP_DSP_DEVSTATE_DELING;
+ dev->state = TASKDEV_ST_DELING;
if (mutex_lock_interruptible(&cfg_lock)) {
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);
+ cfg_tid = TID_ANON;
+ cfg_cmd = MBX_CMD_DSP_TDEL;
+ mbcompose_send_and_wait(TDEL, tid, TDEL_KILL, &cfg_wait_q);
tid_response = cfg_tid;
- cfg_tid = OMAP_DSP_TID_ANON;
+ cfg_tid = TID_ANON;
cfg_cmd = 0;
mutex_unlock(&cfg_lock);
"DSP side could be corrupted.\n");
fail_out:
- dev->state = OMAP_DSP_DEVSTATE_ADDFAIL;
+ dev->state = TASKDEV_ST_ADDFAIL;
wake_up_interruptible_all(&dev->state_wait_q);
return ret;
}
-int dsp_tdel(unsigned char minor)
+int dsp_tadd_minor(unsigned char minor, dsp_long_t adr)
{
struct taskdev *dev;
+ int status;
+ int ret;
+
+ if (mutex_lock_interruptible(&devmgr_lock))
+ return -EINTR;
if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
printk(KERN_ERR
"omapdsp: no task device with minor %d\n", minor);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
- spin_lock(&dev->state_lock);
- if (!(dev->state & OMAP_DSP_DEVSTATE_DELREQ)) {
+ ret = minor;
+ if ((status = dsp_tadd(dev, adr)) < 0)
+ ret = status;
+
+out:
+ mutex_unlock(&devmgr_lock);
+ return ret;
+}
+
+static int dsp_tdel(struct taskdev *dev)
+{
+ if (!devstate_write_lock_and_test(dev, TASKDEV_ST_DELREQ)) {
printk(KERN_ERR
"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);
+ dev->state = TASKDEV_ST_DELING;
+ devstate_write_unlock(dev);
- return dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_SAFE);
+ return dsp_tdel_bh(dev, TDEL_SAFE);
}
-int dsp_tkill(unsigned char minor)
+int dsp_tdel_minor(unsigned char minor)
{
struct taskdev *dev;
+ int status;
+ int ret;
+
+ if (mutex_lock_interruptible(&devmgr_lock))
+ return -EINTR;
if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
printk(KERN_ERR
"omapdsp: no task device with minor %d\n", minor);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = minor;
+ if ((status = dsp_tdel(dev)) < 0)
+ ret = status;
+
+out:
+ mutex_unlock(&devmgr_lock);
+ return ret;
+}
+
+static int dsp_tkill(struct taskdev *dev)
+{
+ while (!down_write_trylock(&dev->state_sem)) {
+ if (!devstate_read_lock_and_test(dev, (TASKDEV_ST_ATTACHED |
+ TASKDEV_ST_FREEZED))) {
+ printk(KERN_ERR
+ "omapdsp: task has not been attached for "
+ "taskdev %s\n", dev->name);
+ return -EINVAL;
+ }
+ /* ATTACHED -> FREEZED can be changed under read semaphore. */
+ dev->state = TASKDEV_ST_FREEZED;
+ wake_up_interruptible_all(&dev->read_wait_q);
+ wake_up_interruptible_all(&dev->write_wait_q);
+ wake_up_interruptible_all(&dev->tctl_wait_q);
+ devstate_read_unlock(dev);
+ schedule();
}
- spin_lock(&dev->state_lock);
- if (!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED)) {
+
+ if (!(dev->state & (TASKDEV_ST_ATTACHED |
+ TASKDEV_ST_FREEZED))) {
printk(KERN_ERR
"omapdsp: task has not been attached for taskdev %s\n",
dev->name);
- spin_unlock(&dev->state_lock);
+ devstate_write_unlock(dev);
+ return -EINVAL;
+ }
+ if (!is_dynamic_task(dev->task->tid)) {
+ printk(KERN_ERR "omapdsp: task %s is not a dynamic task.\n",
+ dev->name);
+ devstate_write_unlock(dev);
return -EINVAL;
}
- dev->state = OMAP_DSP_DEVSTATE_KILLING;
- proclist_send_sigbus(&dev->proc_list);
- spin_unlock(&dev->state_lock);
+ dev->state = TASKDEV_ST_KILLING;
+ devstate_write_unlock(dev);
- return dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_KILL);
+ return dsp_tdel_bh(dev, TDEL_KILL);
}
-static int dsp_tdel_bh(unsigned char minor, unsigned short type)
+int dsp_tkill_minor(unsigned char minor)
+{
+ struct taskdev *dev;
+ int status;
+ int ret;
+
+ if (mutex_lock_interruptible(&devmgr_lock))
+ return -EINTR;
+
+ if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
+ printk(KERN_ERR
+ "omapdsp: no task device with minor %d\n", minor);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = minor;
+ if ((status = dsp_tkill(dev)) < 0)
+ ret = status;
+
+out:
+ mutex_unlock(&devmgr_lock);
+ return ret;
+}
+
+static int dsp_tdel_bh(struct taskdev *dev, u16 type)
{
- struct taskdev *dev = taskdev[minor];
struct dsptask *task;
- struct mbcmd mb;
- unsigned char tid, tid_response;
- int ret = minor;
+ u8 tid, tid_response;
+ int ret = 0;
task = dev->task;
tid = task->tid;
if (mutex_lock_interruptible(&cfg_lock)) {
- if (type == OMAP_DSP_MBCMD_TDEL_SAFE) {
- dev->state = OMAP_DSP_DEVSTATE_DELREQ;
- return -ERESTARTSYS;
+ if (type == TDEL_SAFE) {
+ dev->state = TASKDEV_ST_DELREQ;
+ return -EINTR;
} else {
- tid_response = OMAP_DSP_TID_ANON;
- ret = -ERESTARTSYS;
+ tid_response = TID_ANON;
+ ret = -EINTR;
goto detach_out;
}
}
- cfg_tid = OMAP_DSP_TID_ANON;
- cfg_cmd = MBCMD(TDEL);
- mbcmd_set(mb, MBCMD(TDEL), tid, type);
- dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
+ cfg_tid = TID_ANON;
+ cfg_cmd = MBX_CMD_DSP_TDEL;
+ mbcompose_send_and_wait(TDEL, tid, type, &cfg_wait_q);
tid_response = cfg_tid;
- cfg_tid = OMAP_DSP_TID_ANON;
+ cfg_tid = TID_ANON;
cfg_cmd = 0;
mutex_unlock(&cfg_lock);
if (tid_response != tid) {
printk(KERN_ERR "omapdsp: %s failed!\n",
- (type == OMAP_DSP_MBCMD_TDEL_SAFE) ? "tdel" : "tkill");
+ (type == TDEL_SAFE) ? "tdel" : "tkill");
ret = -EINVAL;
}
- spin_lock(&dev->state_lock);
- dev->state = (dev->usecount > 0) ? OMAP_DSP_DEVSTATE_GARBAGE :
- OMAP_DSP_DEVSTATE_NOTASK;
+ down_write(&dev->state_sem);
+ dev->state = (dev->usecount > 0) ? TASKDEV_ST_GARBAGE :
+ TASKDEV_ST_NOTASK;
wake_up_interruptible_all(&dev->state_wait_q);
- spin_unlock(&dev->state_lock);
+ up_write(&dev->state_sem);
return ret;
}
{
if (taskdev[minor]) {
long state = taskdev[minor]->state;
- taskdev[minor]->state |= OMAP_DSP_DEVSTATE_STALE;
+ taskdev[minor]->state |= TASKDEV_ST_STALE;
return state;
} else
- return OMAP_DSP_DEVSTATE_NOTASK;
+ return TASKDEV_ST_NOTASK;
}
/*
- * functions called from mailbox1 interrupt routine
+ * functions called from mailbox interrupt routine
*/
-void mbx1_wdsnd(struct mbcmd *mb)
+void mbx_wdsnd(struct mbcmd *mb)
{
- unsigned char tid = mb->cmd_l;
+ u8 tid = mb->cmd_l;
struct dsptask *task = dsptask[tid];
if ((tid >= TASKDEV_MAX) || (task == NULL)) {
return;
}
- write_word_to_fifo(&task->rcvdt.fifo, mb->data);
+ write_word_to_fifo(&task->dev->rcvdt.fifo, mb->data);
wake_up_interruptible(&task->dev->read_wait_q);
}
-void mbx1_wdreq(struct mbcmd *mb)
+void mbx_wdreq(struct mbcmd *mb)
{
- unsigned char tid = mb->cmd_l;
+ u8 tid = mb->cmd_l;
struct dsptask *task = dsptask[tid];
+ struct taskdev *dev;
if ((tid >= TASKDEV_MAX) || (task == NULL)) {
printk(KERN_ERR "mbx: WDREQ with illegal tid! %d\n", tid);
return;
}
- spin_lock(&task->wsz_lock);
- task->wsz = 2;
- spin_unlock(&task->wsz_lock);
- wake_up_interruptible(&task->dev->write_wait_q);
+ dev = task->dev;
+ spin_lock(&dev->wsz_lock);
+ dev->wsz = 2;
+ spin_unlock(&dev->wsz_lock);
+ wake_up_interruptible(&dev->write_wait_q);
}
-void mbx1_bksnd(struct mbcmd *mb)
+void mbx_bksnd(struct mbcmd *mb)
{
- unsigned char tid = mb->cmd_l;
- unsigned short bid = mb->data;
+ u8 tid = mb->cmd_l;
+ u16 bid = mb->data;
struct dsptask *task = dsptask[tid];
- unsigned short cnt;
+ struct ipbuf_head *ipb_h;
+ u16 cnt;
if (bid >= ipbcfg.ln) {
printk(KERN_ERR "mbx: BKSND with illegal bid! %d\n", bid);
return;
}
+ ipb_h = bid_to_ipbuf(bid);
ipb_bsycnt_dec(&ipbcfg);
if ((tid >= TASKDEV_MAX) || (task == NULL)) {
printk(KERN_ERR "mbx: BKSND with illegal tid! %d\n", tid);
"mbx: BKSND from private sending task! (task%d)\n", tid);
goto unuse_ipbuf_out;
}
- if (sync_with_dsp(&ipbuf[bid]->sd, tid, 10) < 0) {
+ if (sync_with_dsp(&ipb_h->p->sd, tid, 10) < 0) {
printk(KERN_ERR "mbx: BKSND - IPBUF sync failed!\n");
return;
}
/* should be done in DSP, but just in case. */
- ipbuf[bid]->next = OMAP_DSP_BID_NULL;
+ ipb_h->p->next = BID_NULL;
- cnt = ipbuf[bid]->c;
+ cnt = ipb_h->p->c;
if (cnt > ipbcfg.lsz) {
printk(KERN_ERR "mbx: BKSND cnt(%d) > ipbuf line size(%d)!\n",
cnt, ipbcfg.lsz);
if (cnt == 0) {
/* 0-byte send from DSP */
- unuse_ipbuf_nowait(bid);
+ unuse_ipbuf_nowait(ipb_h);
goto done;
}
- spin_lock(&task->rcvdt.bk.link.lock);
- ipblink_add_tail(&task->rcvdt.bk.link, bid, ipbuf);
- spin_unlock(&task->rcvdt.bk.link.lock);
+ ipblink_add_tail(&task->dev->rcvdt.bk.link, bid);
/* we keep coming bid and return alternative line to DSP. */
balance_ipbuf();
return;
unuse_ipbuf_out:
- unuse_ipbuf_nowait(bid);
+ unuse_ipbuf_nowait(ipb_h);
return;
}
-void mbx1_bkreq(struct mbcmd *mb)
+void mbx_bkreq(struct mbcmd *mb)
{
- unsigned char tid = mb->cmd_l;
- unsigned short cnt = mb->data;
+ u8 tid = mb->cmd_l;
+ u16 cnt = mb->data;
struct dsptask *task = dsptask[tid];
+ struct taskdev *dev;
if ((tid >= TASKDEV_MAX) || (task == NULL)) {
printk(KERN_ERR "mbx: BKREQ with illegal tid! %d\n", tid);
return;
}
- spin_lock(&task->wsz_lock);
- task->wsz = cnt*2;
- spin_unlock(&task->wsz_lock);
- wake_up_interruptible(&task->dev->write_wait_q);
+ dev = task->dev;
+ spin_lock(&dev->wsz_lock);
+ dev->wsz = cnt*2;
+ spin_unlock(&dev->wsz_lock);
+ wake_up_interruptible(&dev->write_wait_q);
}
-void mbx1_bkyld(struct mbcmd *mb)
+void mbx_bkyld(struct mbcmd *mb)
{
- unsigned short bid = mb->data;
+ u16 bid = mb->data;
+ struct ipbuf_head *ipb_h;
if (bid >= ipbcfg.ln) {
printk(KERN_ERR "mbx: BKYLD with illegal bid! %d\n", bid);
return;
}
+ ipb_h = bid_to_ipbuf(bid);
/* should be done in DSP, but just in case. */
- ipbuf[bid]->next = OMAP_DSP_BID_NULL;
+ ipb_h->p->next = BID_NULL;
/* we don't need to sync with DSP */
ipb_bsycnt_dec(&ipbcfg);
- release_ipbuf(bid);
+ release_ipbuf(ipb_h);
}
-void mbx1_bksndp(struct mbcmd *mb)
+void mbx_bksndp(struct mbcmd *mb)
{
- unsigned char tid = mb->cmd_l;
+ u8 tid = mb->cmd_l;
struct dsptask *task = dsptask[tid];
- struct rcvdt_bk_struct *rcvdt = &task->rcvdt.bk;
- struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r;
+ struct ipbuf_p *ipbp;
if ((tid >= TASKDEV_MAX) || (task == NULL)) {
printk(KERN_ERR "mbx: BKSNDP with illegal tid! %d\n", tid);
* until then DSP can't send next data.
*/
+ ipbp = task->ipbuf_pvt_r;
if (sync_with_dsp(&ipbp->s, tid, 10) < 0) {
printk(KERN_ERR "mbx: BKSNDP - IPBUF sync failed!\n");
return;
}
printk(KERN_DEBUG "mbx: ipbuf_pvt_r->a = 0x%08lx\n",
MKLONG(ipbp->ah, ipbp->al));
- spin_lock(&rcvdt->link.lock);
- ipblink_add_pvt(&rcvdt->link);
- spin_unlock(&rcvdt->link.lock);
+ ipblink_add_pvt(&task->dev->rcvdt.bk.link);
wake_up_interruptible(&task->dev->read_wait_q);
}
-void mbx1_bkreqp(struct mbcmd *mb)
+void mbx_bkreqp(struct mbcmd *mb)
{
- unsigned char tid = mb->cmd_l;
+ u8 tid = mb->cmd_l;
struct dsptask *task = dsptask[tid];
- struct ipbuf_p *ipbp = task->ipbuf_pvt_w;
+ struct taskdev *dev;
+ struct ipbuf_p *ipbp;
if ((tid >= TASKDEV_MAX) || (task == NULL)) {
printk(KERN_ERR "mbx: BKREQP with illegal tid! %d\n", tid);
return;
}
- if (sync_with_dsp(&ipbp->s, OMAP_DSP_TID_FREE, 10) < 0) {
+ ipbp = task->ipbuf_pvt_w;
+ if (sync_with_dsp(&ipbp->s, TID_FREE, 10) < 0) {
printk(KERN_ERR "mbx: BKREQP - IPBUF sync failed!\n");
return;
}
printk(KERN_DEBUG "mbx: ipbuf_pvt_w->a = 0x%08lx\n",
MKLONG(ipbp->ah, ipbp->al));
- spin_lock(&task->wsz_lock);
- task->wsz = ipbp->c*2;
- spin_unlock(&task->wsz_lock);
- wake_up_interruptible(&task->dev->write_wait_q);
+ dev = task->dev;
+ spin_lock(&dev->wsz_lock);
+ dev->wsz = ipbp->c*2;
+ spin_unlock(&dev->wsz_lock);
+ wake_up_interruptible(&dev->write_wait_q);
}
-void mbx1_tctl(struct mbcmd *mb)
+void mbx_tctl(struct mbcmd *mb)
{
- unsigned char tid = mb->cmd_l;
+ u8 tid = mb->cmd_l;
struct dsptask *task = dsptask[tid];
if ((tid >= TASKDEV_MAX) || (task == NULL)) {
return;
}
- if (!waitqueue_active(&task->dev->ioctl_wait_q)) {
+ if (!waitqueue_active(&task->dev->tctl_wait_q)) {
printk(KERN_WARNING "mbx: unexpected TCTL from DSP!\n");
return;
}
- task->tctl_stat = mb->data;
- wake_up_interruptible(&task->dev->ioctl_wait_q);
+ task->dev->tctl_stat = mb->data;
+ wake_up_interruptible(&task->dev->tctl_wait_q);
}
-void mbx1_tcfg(struct mbcmd *mb)
+void mbx_tcfg(struct mbcmd *mb)
{
- unsigned char tid = mb->cmd_l;
+ u8 tid = mb->cmd_l;
struct dsptask *task = dsptask[tid];
- unsigned short *tnm;
- volatile unsigned short *buf;
+ u16 *tnm;
+ volatile u16 *buf;
int i;
if ((tid >= TASKDEV_MAX) || (task == NULL)) {
printk(KERN_ERR "mbx: TCFG with illegal tid! %d\n", tid);
return;
}
- if ((task->state != TASK_STATE_CFGREQ) || (cfg_cmd != MBCMD(TCFG))) {
+ if ((task->state != TASK_ST_CFGREQ) || (cfg_cmd != MBX_CMD_DSP_TCFG)) {
printk(KERN_WARNING "mbx: unexpected TCFG from DSP!\n");
return;
}
+ if (dsp_mem_enable(ipbuf_sys_da) < 0) {
+ printk(KERN_ERR "mbx: TCFG - ipbuf_sys_da read failed!\n");
+ dsp_mem_disable(ipbuf_sys_da);
+ goto out;
+ }
if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
printk(KERN_ERR "mbx: TCFG - IPBUF sync failed!\n");
+ dsp_mem_disable(ipbuf_sys_da);
goto out;
}
* read configuration data on system IPBUF
*/
buf = ipbuf_sys_da->d;
- 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]);
+ task->ttyp = buf[0];
+ task->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);
+ dsp_mem_disable(ipbuf_sys_da);
/*
* copy task name string
*/
- if (dsp_address_validate(tnm, OMAP_DSP_TNM_LEN, "task name buffer") <0) {
+ if (dsp_address_validate(tnm, TNM_LEN, "task name buffer") < 0) {
task->name[0] = '\0';
goto out;
}
- for (i = 0; i < OMAP_DSP_TNM_LEN-1; i++) {
+ for (i = 0; i < TNM_LEN-1; i++) {
/* avoiding byte access */
- unsigned short tmp = tnm[i];
+ u16 tmp = tnm[i];
task->name[i] = tmp & 0x00ff;
if (!tmp)
break;
}
- task->name[OMAP_DSP_TNM_LEN-1] = '\0';
+ task->name[TNM_LEN-1] = '\0';
- task->state = TASK_STATE_READY;
+ task->state = TASK_ST_READY;
out:
wake_up_interruptible(&cfg_wait_q);
}
-void mbx1_tadd(struct mbcmd *mb)
+void mbx_tadd(struct mbcmd *mb)
{
- unsigned char tid = mb->cmd_l;
+ u8 tid = mb->cmd_l;
- if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBCMD(TADD))) {
+ if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBX_CMD_DSP_TADD)) {
printk(KERN_WARNING "mbx: unexpected TADD from DSP!\n");
return;
}
wake_up_interruptible(&cfg_wait_q);
}
-void mbx1_tdel(struct mbcmd *mb)
+void mbx_tdel(struct mbcmd *mb)
{
- unsigned char tid = mb->cmd_l;
+ u8 tid = mb->cmd_l;
- if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBCMD(TDEL))) {
+ if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBX_CMD_DSP_TDEL)) {
printk(KERN_WARNING "mbx: unexpected TDEL from DSP!\n");
return;
}
wake_up_interruptible(&cfg_wait_q);
}
-void mbx1_err_fatal(unsigned char tid)
+void mbx_err_fatal(u8 tid)
{
struct dsptask *task = dsptask[tid];
+ struct taskdev *dev;
if ((tid >= TASKDEV_MAX) || (task == NULL)) {
printk(KERN_ERR "mbx: FATAL ERR with illegal tid! %d\n", tid);
return;
}
- spin_lock(&task->dev->state_lock);
- proclist_send_sigbus(&task->dev->proc_list);
- spin_unlock(&task->dev->state_lock);
+ /* wake up waiting processes */
+ dev = task->dev;
+ wake_up_interruptible_all(&dev->read_wait_q);
+ wake_up_interruptible_all(&dev->write_wait_q);
+ wake_up_interruptible_all(&dev->tctl_wait_q);
}
-static short *dbg_buf;
-static unsigned short dbg_buf_sz, dbg_line_sz;
+static u16 *dbg_buf;
+static u16 dbg_buf_sz, dbg_line_sz;
static int dbg_rp;
-int dsp_dbg_config(short *buf, unsigned short sz, unsigned short lsz)
+int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz)
{
#ifdef OLD_BINARY_SUPPORT
if ((mbx_revision == MBREV_3_0) || (mbx_revision == MBREV_3_2)) {
}
#ifdef OLD_BINARY_SUPPORT
-static void mbx1_dbg_old(struct mbcmd *mb);
+static void mbx_dbg_old(struct mbcmd *mb);
#endif
-void mbx1_dbg(struct mbcmd *mb)
+void mbx_dbg(struct mbcmd *mb)
{
- unsigned char tid = mb->cmd_l;
+ u8 tid = mb->cmd_l;
int cnt = mb->data;
char s[80], *s_end = &s[79], *p;
- unsigned short *src;
+ u16 *src;
int i;
#ifdef OLD_BINARY_SUPPORT
if ((mbx_revision == MBREV_3_0) || (mbx_revision == MBREV_3_2)) {
- mbx1_dbg_old(mb);
+ mbx_dbg_old(mb);
return;
}
#endif
if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
- (tid != OMAP_DSP_TID_ANON)) {
+ (tid != TID_ANON)) {
printk(KERN_ERR "mbx: DBG with illegal tid! %d\n", tid);
return;
}
src = &dbg_buf[dbg_rp];
p = s;
for (i = 0; i < cnt; i++) {
- unsigned short tmp;
+ u16 tmp;
/*
* Be carefull that dbg_buf should not be read with
* 1-byte access since it might be placed in DARAM/SARAM
}
#ifdef OLD_BINARY_SUPPORT
-static void mbx1_dbg_old(struct mbcmd *mb)
+static void mbx_dbg_old(struct mbcmd *mb)
{
- unsigned char tid = mb->cmd_l;
+ u8 tid = mb->cmd_l;
char s[80], *s_end = &s[79], *p;
- unsigned short *src;
- volatile unsigned short *buf;
+ u16 *src;
+ volatile u16 *buf;
int cnt;
int i;
if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
- (tid != OMAP_DSP_TID_ANON)) {
+ (tid != TID_ANON)) {
printk(KERN_ERR "mbx: DBG with illegal tid! %d\n", tid);
return;
}
+ if (dsp_mem_enable(ipbuf_sys_da) < 0) {
+ printk(KERN_ERR "mbx: DBG - ipbuf_sys_da read failed!\n");
+ return;
+ }
if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
printk(KERN_ERR "mbx: DBG - IPBUF sync failed!\n");
- return;
+ goto out1;
}
buf = ipbuf_sys_da->d;
cnt = buf[0];
src = MKVIRT(buf[1], buf[2]);
if (dsp_address_validate(src, cnt, "dbg buffer") < 0)
- return;
+ goto out2;
if (dsp_mem_enable(src) < 0)
- return;
+ goto out2;
p = s;
for (i = 0; i < cnt; i++) {
- unsigned short tmp;
+ u16 tmp;
/*
* Be carefull that ipbuf should not be read with
* 1-byte access since it might be placed in DARAM/SARAM
printk(KERN_INFO "%s\n", s);
}
- release_ipbuf_pvt(ipbuf_sys_da);
dsp_mem_disable(src);
+out2:
+ release_ipbuf_pvt(ipbuf_sys_da);
+out1:
+ dsp_mem_disable(ipbuf_sys_da);
}
#endif /* OLD_BINARY_SUPPORT */
/*
- * sysfs files
+ * sysfs files: for each device
*/
+
+/* devname */
static ssize_t devname_show(struct device *d, struct device_attribute *attr,
char *buf)
{
- struct taskdev *dev = to_taskdev(d);
- return sprintf(buf, "%s\n", dev->name);
+ return sprintf(buf, "%s\n", to_taskdev(d)->name);
}
+/* devstate */
static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
char *buf)
{
- struct taskdev *dev = to_taskdev(d);
- return sprintf(buf, "%s\n", devstate_name(dev->state));
+ return sprintf(buf, "%s\n", devstate_name(to_taskdev(d)->state));
}
+/* proc_list */
static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
char *buf)
{
int len = 0;
dev = to_taskdev(d);
- spin_lock(&dev->state_lock);
+ spin_lock(&dev->proc_list_lock);
list_for_each_entry(pl, &dev->proc_list, list_head) {
- len += sprintf(buf + len, "%d\n", pl->pid);
+ /* need to lock tasklist_lock before calling
+ * find_task_by_pid_type. */
+ if (find_task_by_pid_type(PIDTYPE_PID, pl->pid) != NULL)
+ len += sprintf(buf + len, "%d\n", pl->pid);
+ read_unlock(&tasklist_lock);
}
- spin_unlock(&dev->state_lock);
+ spin_unlock(&dev->proc_list_lock);
return len;
}
+/* taskname */
static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
char *buf)
{
struct taskdev *dev = to_taskdev(d);
int len;
+ if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+ return -ENODEV;
+
len = sprintf(buf, "%s\n", dev->task->name);
+ devstate_read_unlock(dev);
return len;
}
+/* ttyp */
static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
char *buf)
{
- unsigned short ttyp = to_taskdev(d)->task->ttyp;
+ struct taskdev *dev = to_taskdev(d);
+ u16 ttyp;
int len = 0;
+ if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+ return -ENODEV;
+
+ ttyp = dev->task->ttyp;
len += sprintf(buf + len, "0x%04x\n", ttyp);
len += sprintf(buf + len, "%s %s send\n",
(sndtyp_acv(ttyp)) ? "active" :
(rcvtyp_pvt(ttyp)) ? "private block" :
"global block");
+ devstate_read_unlock(dev);
return len;
}
+/* fifosz */
static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
char *buf)
{
- struct fifo_struct *fifo = &to_taskdev(d)->task->rcvdt.fifo;
+ struct fifo_struct *fifo = &to_taskdev(d)->rcvdt.fifo;
return sprintf(buf, "%d\n", fifo->sz);
}
static int fifosz_store(struct device *d, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct dsptask *task = to_taskdev(d)->task;
+ struct taskdev *dev = to_taskdev(d);
unsigned long fifosz;
int ret;
fifosz = simple_strtol(buf, NULL, 10);
- ret = dsp_task_set_fifosz(task, fifosz);
+ ret = taskdev_set_fifosz(dev, fifosz);
return (ret < 0) ? ret : strlen(buf);
}
+/* fifocnt */
static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
char *buf)
{
- struct fifo_struct *fifo = &to_taskdev(d)->task->rcvdt.fifo;
+ struct fifo_struct *fifo = &to_taskdev(d)->rcvdt.fifo;
return sprintf(buf, "%d\n", fifo->cnt);
}
-static __inline__ char *bid_name(unsigned short bid)
+/* ipblink */
+static __inline__ char *bid_name(u16 bid)
{
static char s[6];
switch (bid) {
- case OMAP_DSP_BID_NULL:
+ case BID_NULL:
return "NULL";
- case OMAP_DSP_BID_PVT:
+ case BID_PVT:
return "PRIVATE";
default:
sprintf(s, "%d", bid);
static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
char *buf)
{
- struct rcvdt_bk_struct *rcvdt = &to_taskdev(d)->task->rcvdt.bk;
+ struct rcvdt_bk_struct *rcvdt = &to_taskdev(d)->rcvdt.bk;
int len;
spin_lock(&rcvdt->link.lock);
return len;
}
+/* wsz */
static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
char *buf)
{
- return sprintf(buf, "%d\n", to_taskdev(d)->task->wsz);
+ return sprintf(buf, "%d\n", to_taskdev(d)->wsz);
}
+/* mmap */
static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
char *buf)
{
}
/*
- * called from ipbuf_read_proc()
+ * called from ipbuf_show()
*/
-int ipbuf_is_held(unsigned char tid, unsigned short bid)
+int ipbuf_is_held(u8 tid, u16 bid)
{
struct dsptask *task = dsptask[tid];
- unsigned short b;
+ struct ipblink *link;
+ u16 b;
int ret = 0;
if (task == NULL)
return 0;
- spin_lock(&task->rcvdt.bk.link.lock);
- ipblink_for_each(b, &task->rcvdt.bk.link, ipbuf) {
+ link = &task->dev->rcvdt.bk.link;
+ spin_lock(&link->lock);
+ ipblink_for_each(b, link) {
if (b == bid) { /* found */
ret = 1;
break;
}
}
- spin_unlock(&task->rcvdt.bk.link.lock);
+ spin_unlock(&link->lock);
return ret;
}
/*
- * linux/arch/arm/mach-omap/dsp/taskwatch.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * OMAP DSP task watch device driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 200%/05/16: DSP Gateway version 3.3
*/
#include <linux/module.h>
-#include <linux/major.h>
-#include <linux/init.h>
#include <linux/fs.h>
#include <linux/poll.h>
-#include <linux/interrupt.h>
#include <linux/sched.h>
-#include <linux/mutex.h>
#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/arch/dsp.h>
+#include "dsp_mbcmd.h"
#include "dsp.h"
+#include "ioctl.h"
static DECLARE_WAIT_QUEUE_HEAD(read_wait_q);
static unsigned int change_cnt;
/*
* @count: represents the device counts of the user's interst
*/
-static ssize_t dsp_twch_read(struct file *file, char *buf, size_t count,
+static ssize_t dsp_twch_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
long taskstat[TASKDEV_MAX];
int devcount = count / sizeof(long);
int i;
- if (!dsp_is_ready()) {
+ if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
return -EINVAL;
}
remove_wait_queue(&read_wait_q, &wait);
/* unconfigured while waiting ;-( */
- if (dsp_is_ready())
+ if (dsp_cfgstat_get_stat() != CFGSTAT_READY)
return -EINVAL;
}
static int dsp_twch_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- static DEFINE_MUTEX(ioctl_lock);
int ret;
- if (mutex_lock_interruptible(&ioctl_lock))
- return -ERESTARTSYS;
-
switch (cmd) {
- case OMAP_DSP_TWCH_IOCTL_MKDEV:
+ case TWCH_IOCTL_MKDEV:
{
- char name[OMAP_DSP_TNM_LEN];
- if (copy_from_user(name, (void *)arg, OMAP_DSP_TNM_LEN)) {
- ret = -EFAULT;
- goto up_out;
- }
- name[OMAP_DSP_TNM_LEN-1] = '\0';
+ char name[TNM_LEN];
+ if (copy_from_user(name, (void __user *)arg, TNM_LEN))
+ return -EFAULT;
+ name[TNM_LEN-1] = '\0';
ret = dsp_mkdev(name);
break;
}
- case OMAP_DSP_TWCH_IOCTL_RMDEV:
+ case TWCH_IOCTL_RMDEV:
{
- char name[OMAP_DSP_TNM_LEN];
- if (copy_from_user(name, (void *)arg, OMAP_DSP_TNM_LEN)) {
- ret = -EFAULT;
- goto up_out;
- }
- name[OMAP_DSP_TNM_LEN-1] = '\0';
+ char name[TNM_LEN];
+ if (copy_from_user(name, (void __user *)arg, TNM_LEN))
+ return -EFAULT;
+ name[TNM_LEN-1] = '\0';
ret = dsp_rmdev(name);
break;
}
- case OMAP_DSP_TWCH_IOCTL_TADD:
+ case TWCH_IOCTL_TADD:
{
struct omap_dsp_taddinfo ti;
- if (copy_from_user(&ti, (void *)arg, sizeof(ti))) {
- ret = -EFAULT;
- goto up_out;
- }
- ret = dsp_tadd(ti.minor, ti.taskadr);
+ if (copy_from_user(&ti, (void __user *)arg, sizeof(ti)))
+ return -EFAULT;
+ ret = dsp_tadd_minor(ti.minor, ti.taskadr);
break;
}
- case OMAP_DSP_TWCH_IOCTL_TDEL:
- ret = dsp_tdel(arg);
+ case TWCH_IOCTL_TDEL:
+ ret = dsp_tdel_minor(arg);
break;
- case OMAP_DSP_TWCH_IOCTL_TKILL:
- ret = dsp_tkill(arg);
+ case TWCH_IOCTL_TKILL:
+ ret = dsp_tkill_minor(arg);
break;
default:
- ret = -ENOIOCTLCMD;
+ return -ENOIOCTLCMD;
}
-up_out:
- mutex_unlock(&ioctl_lock);
return ret;
}
/*
- * linux/arch/arm/mach-omap/dsp/uaccess_dsp.S
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * user memory access functions for DSP driver
+ * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2004,2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2004/06/29: DSP Gateway version 3.3
*/
#include <linux/linkage.h>
/*
- * linux/arch/arm/mach-omap/dsp/uaccess_dsp.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * Header for user access functions for DSP driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Modified from linux/include/asm-arm/uaccess.h
- * by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2004/06/29: DSP Gateway version 3.3
*/
#ifndef _OMAP_DSP_UACCESS_DSP_H
#define _OMAP_DSP_UACCESS_DSP_H
#include <asm/uaccess.h>
+#include "dsp_common.h"
#define HAVE_ASM_COPY_FROM_USER_DSP_2B
const void *from);
#endif
-extern unsigned long dspmem_base, dspmem_size;
-#define is_dsp_internal_mem(va) \
- (((unsigned long)(va) >= dspmem_base) && \
- ((unsigned long)(va) < dspmem_base + dspmem_size))
-
-
#ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
static __inline__ unsigned long copy_from_user_dsp_2b(void *to,
const void *from)
return n;
}
-#undef is_dsp_internal_mem
-
#endif /* _OMAP_DSP_UACCESS_DSP_H */
--- /dev/null
+/*
+ * OMAP mailbox driver
+ *
+ * Copyright (C) 2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#ifdef CONFIG_ARCH_OMAP2
+#include <linux/clk.h>
+#endif
+#include <asm/io.h>
+#ifdef CONFIG_ARCH_OMAP1
+#include <asm/delay.h>
+#endif
+#include <asm/arch/mailbox.h>
+#include "mailbox_hw.h"
+
+#if defined(CONFIG_ARCH_OMAP1)
+
+#define read_mbx(m, msgp) \
+ do { \
+ *(msgp) = omap_readw((m)->data_r); \
+ *(msgp) |= ((mbx_msg_t)omap_readw((m)->cmd_r)) << 16; \
+ } while (0)
+#define write_mbx(m, msg) \
+ do { \
+ omap_writew((msg) & 0xffff, (m)->data_w); \
+ omap_writew((msg) >> 16, (m)->cmd_w); \
+ } while (0)
+#define enable_newmsg_irq(m) enable_irq((m)->irq)
+#define disable_newmsg_irq(m) disable_irq((m)->irq)
+#define mbx_is_notfull(m) (omap_readw((m)->flag_w) == 0)
+
+#elif defined(CONFIG_ARCH_OMAP2)
+
+#define omap_bit_setl(b,r) \
+ do { omap_writel(omap_readl(r) | (b), (r)); } while(0)
+#define omap_bit_clrl(b,r) \
+ do { omap_writel(omap_readl(r) & ~(b), (r)); } while(0)
+
+#define read_mbx(m, msgp) \
+ do { *(msgp) = omap_readl((m)->message_r); } while (0)
+#define write_mbx(m, msg) omap_writel(msg, (m)->message_w)
+#define enable_newmsg_irq(m) omap_bit_setl((m)->newmsg_bit, (m)->irqenable)
+#define disable_newmsg_irq(m) omap_bit_clrl((m)->newmsg_bit, (m)->irqenable)
+#define enable_notfull_irq(m) omap_bit_setl((m)->notfull_bit, (m)->irqenable)
+#define disable_notfull_irq(m) omap_bit_clrl((m)->notfull_bit, (m)->irqenable)
+#define clear_newmsg_irq(m) omap_writel((m)->newmsg_bit, (m)->irqstatus)
+#define clear_notfull_irq(m) omap_writel((m)->notfull_bit, (m)->irqstatus)
+#define notfull_irq_enabled(m) (omap_readl((m)->irqenable) & (m)->notfull_bit)
+#define has_newmsg_irq(m) (omap_readl((m)->irqstatus) & (m)->newmsg_bit)
+#define has_notfull_irq(m) (omap_readl((m)->irqstatus) & (m)->notfull_bit)
+#define mbx_nomsg(m) (omap_readl((m)->msgstatus_r) == 0)
+#define mbx_is_notfull(m) (omap_readl((m)->fifostatus_w) == 0)
+
+#endif /* CONFIG_ARCH_OMAP2 */
+
+static void do_mbx(void *p);
+
+#define MBQ_DEPTH 16
+struct mbq {
+ mbx_msg_t msg[MBQ_DEPTH];
+ int rp, wp, full;
+};
+
+#define mbq_inc(p) do { if (++(p) == MBQ_DEPTH) (p) = 0; } while(0)
+
+#if defined(CONFIG_ARCH_OMAP1)
+# define MBX_USE_SEQ_BIT /* XXX */
+#elif defined(CONFIG_ARCH_OMAP2)
+# undef MBX_USE_SEQ_BIT
+#endif
+
+struct mbx {
+ char *name;
+ unsigned int irq;
+ char irq_devid_newmsg;
+#ifdef CONFIG_ARCH_OMAP2
+ char irq_devid_notfull;
+#endif
+#ifdef MBX_USE_SEQ_BIT
+ mbx_msg_t seq_snd;
+ mbx_msg_t seq_rcv;
+ /* seq_rcv should be initialized with any value other than
+ * 0 and 1 << 31, to allow either value for the first
+ * message. */
+#endif
+ mbx_receiver_t *receiver_map[MBX_CMD_MAX];
+ struct work_struct work;
+ struct mbq mbq;
+#ifdef CONFIG_ARCH_OMAP2
+ wait_queue_head_t full_wait_q;
+#endif
+
+#if defined(CONFIG_ARCH_OMAP1)
+ void *cmd_w;
+ void *data_w;
+ void *flag_w;
+ void *cmd_r;
+ void *data_r;
+#elif defined(CONFIG_ARCH_OMAP2)
+ void *irqenable;
+ void *irqstatus;
+ void *message_w;
+ void *message_r;
+ void *fifostatus_w;
+ void *msgstatus_r;
+ u32 notfull_bit;
+ u32 newmsg_bit;
+#endif
+};
+
+#if defined(CONFIG_ARCH_OMAP1)
+
+#if defined(CONFIG_ARCH_OMAP15XX)
+#define INT_DSP_MAILBOX1 INT_1510_DSP_MAILBOX1
+#elif defined(CONFIG_ARCH_OMAP16XX)
+#define INT_DSP_MAILBOX1 INT_1610_DSP_MAILBOX1
+#endif
+
+static struct mbx mbx_dsp = {
+ .name = "DSP",
+ .irq = INT_DSP_MAILBOX1,
+ .work = __WORK_INITIALIZER(mbx_dsp.work, do_mbx, &mbx_dsp),
+
+ .cmd_w = (void *)MAILBOX_ARM2DSP1b,
+ .data_w = (void *)MAILBOX_ARM2DSP1,
+ .flag_w = (void *)MAILBOX_ARM2DSP1_Flag,
+ .cmd_r = (void *)MAILBOX_DSP2ARM1b,
+ .data_r = (void *)MAILBOX_DSP2ARM1,
+};
+
+#elif defined(CONFIG_ARCH_OMAP2)
+
+/*
+ * MAILBOX 0: ARM -> DSP,
+ * MAILBOX 1: ARM <- DSP.
+ * MAILBOX 2: ARM -> IVA,
+ * MAILBOX 3: ARM <- IVA.
+ */
+static struct mbx mbx_dsp = {
+ .name = "DSP",
+ .irq = INT_24XX_MAIL_U0_MPU,
+ .work = __WORK_INITIALIZER(mbx_dsp.work, do_mbx, &mbx_dsp),
+ .full_wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(mbx_dsp.full_wait_q),
+
+ .irqenable = (void *)MAILBOX_IRQENABLE_0,
+ .irqstatus = (void *)MAILBOX_IRQSTATUS_0,
+ .message_w = (void *)MAILBOX_MESSAGE_0,
+ .message_r = (void *)MAILBOX_MESSAGE_1,
+ .fifostatus_w = (void *)MAILBOX_FIFOSTATUS_0,
+ .msgstatus_r = (void *)MAILBOX_MSGSTATUS_1,
+ .notfull_bit = MAILBOX_IRQ_NOTFULL(0),
+ .newmsg_bit = MAILBOX_IRQ_NEWMSG(1),
+};
+static struct mbx mbx_iva = {
+ .name = "IVA",
+ .irq = INT_24XX_MAIL_U3_MPU,
+ .work = __WORK_INITIALIZER(mbx_iva.work, do_mbx, &mbx_iva),
+ .full_wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(mbx_iva.full_wait_q),
+
+ .irqenable = (void *)MAILBOX_IRQENABLE_3,
+ .irqstatus = (void *)MAILBOX_IRQSTATUS_3,
+ .message_w = (void *)MAILBOX_MESSAGE_2,
+ .message_r = (void *)MAILBOX_MESSAGE_3,
+ .fifostatus_w = (void *)MAILBOX_FIFOSTATUS_2,
+ .msgstatus_r = (void *)MAILBOX_MSGSTATUS_3,
+ .notfull_bit = MAILBOX_IRQ_NOTFULL(2),
+ .newmsg_bit = MAILBOX_IRQ_NEWMSG(3),
+};
+
+#endif /* CONFIG_ARCH_OMAP2 */
+
+static struct mbx *mbxes[] = {
+ &mbx_dsp,
+#ifdef CONFIG_ARCH_OMAP2
+ &mbx_iva,
+#endif
+};
+
+struct mbx *mbx_get(const char *id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mbxes); i++) {
+ if (!strcmp(id, mbxes[i]->name))
+ return mbxes[i];
+ }
+
+ return ERR_PTR(-ENOENT);
+}
+
+#if defined(CONFIG_ARCH_OMAP1)
+static __inline__ int mbsync_irq_save(struct mbx *mbx, unsigned long *flags,
+ int try_cnt)
+{
+ int cnt;
+
+ local_irq_save(*flags);
+ if (mbx_is_notfull(mbx))
+ return 0;
+ /*
+ * mailbox is busy. wait for some usecs...
+ */
+ local_irq_restore(*flags);
+ for (cnt = 0; cnt < try_cnt; cnt++) {
+ udelay(1);
+ local_irq_save(*flags);
+ if (mbx_is_notfull(mbx)) /* success! */
+ return 0;
+ local_irq_restore(*flags);
+ }
+
+ /* fail! */
+ return -1;
+}
+#elif defined(CONFIG_ARCH_OMAP2)
+static __inline__ int mbsync_irq_save(struct mbx *mbx, unsigned long *flags)
+{
+ long current_state;
+ DECLARE_WAITQUEUE(wait, current);
+
+ do {
+ local_irq_save(*flags);
+ if (mbx_is_notfull(mbx))
+ return 0;
+
+ /*
+ * mailbox is busy.
+ */
+ local_irq_restore(*flags);
+ enable_notfull_irq(mbx);
+
+ /* wait until the FIFO becomes not-full */
+ add_wait_queue(&mbx->full_wait_q, &wait);
+ current_state = current->state;
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (!mbx_is_notfull(mbx)) /* last check */
+ schedule();
+ set_current_state(current_state);
+ remove_wait_queue(&mbx->full_wait_q, &wait);
+
+ if (signal_pending(current))
+ return -1;
+ } while (1);
+}
+#endif
+
+/*
+ * message dispatcher API
+ */
+int mbx_send(struct mbx *mbx, mbx_msg_t msg)
+{
+ unsigned long flags;
+
+#if defined(CONFIG_ARCH_OMAP1)
+ /*
+ * DSP mailbox interrupt latency must be less than 1ms.
+ */
+ if (mbsync_irq_save(mbx, &flags, 1000) < 0) {
+ printk(KERN_ERR
+ "mailbox(%s) is busy. message 0x%08x is aborting.\n",
+ mbx->name, msg);
+ return -1;
+ }
+#elif defined(CONFIG_ARCH_OMAP2)
+ if (mbsync_irq_save(mbx, &flags) < 0)
+ return -1;
+#endif
+
+#ifdef MBX_USE_SEQ_BIT
+ /* add seq_snd to msg */
+ msg = (msg & 0x7fffffff) | mbx->seq_snd;
+ /* flip seq_snd */
+ mbx->seq_snd ^= 1 << 31;
+#endif
+
+ write_mbx(mbx, msg);
+
+ local_irq_restore(flags);
+ return 0;
+}
+
+/*
+ * register / unregister API
+ */
+int register_mbx_receiver(struct mbx *mbx, unsigned char cmd,
+ mbx_receiver_t *rcv)
+{
+ if (cmd >= MBX_CMD_MAX) {
+ printk(KERN_ERR "register_mbx_receiver(): "
+ "bad cmd (0x%x)\n", cmd);
+ return -EINVAL;
+ }
+ if (mbx->receiver_map[cmd] != NULL) {
+ printk(KERN_ERR "register_mbx_receiver(): cmd 0x%x is "
+ "already reserved.\n", cmd);
+ return -EINVAL;
+ }
+
+ mbx->receiver_map[cmd] = rcv;
+ return 0;
+}
+
+int unregister_mbx_receiver(struct mbx *mbx, unsigned char cmd,
+ mbx_receiver_t *rcv)
+{
+ if (cmd >= MBX_CMD_MAX) {
+ printk(KERN_ERR "unregister_mbx_receiver(): "
+ "bad cmd (0x%x)\n", cmd);
+ return -EINVAL;
+ }
+ if (mbx->receiver_map[cmd] != rcv) {
+ printk(KERN_ERR "unregister_mbx_receiver(): cmd 0x%x and "
+ "receiver function mismatch!\n", cmd);
+ return -EINVAL;
+ }
+
+ mbx->receiver_map[cmd] = NULL;
+ return 0;
+}
+
+/*
+ * IRQ disable / enable API
+ */
+void disable_mbx_irq(struct mbx *mbx)
+{
+ disable_irq(mbx->irq);
+}
+
+void enable_mbx_irq(struct mbx *mbx)
+{
+ enable_irq(mbx->irq);
+}
+
+/*
+ * init_seq API
+ */
+void mbx_init_seq(struct mbx *mbx)
+{
+#ifdef MBX_USE_SEQ_BIT
+ /* backward compatibility */
+ mbx->seq_snd = 0x80000000;
+
+ /* any value other than 0 and 1 << 31 */
+ mbx->seq_rcv = 0xffffffff;
+#endif /* MBX_USE_SEQ_BIT */
+}
+
+/*
+ * receiver workqueue
+ */
+static void do_mbx(void *p)
+{
+ int empty = 0;
+ struct mbx *mbx = (struct mbx *)p;
+ struct mbq *mbq = &mbx->mbq;
+ mbx_receiver_t *receiver;
+ mbx_msg_t msg;
+#ifdef MBX_USE_SEQ_BIT
+ mbx_msg_t seq;
+#endif
+
+ disable_newmsg_irq(mbx);
+ if ((mbq->rp == mbq->wp) && !mbq->full)
+ empty = 1;
+ enable_newmsg_irq(mbx);
+
+ while (!empty) {
+ msg = mbq->msg[mbq->rp];
+#ifdef MBX_USE_SEQ_BIT
+ seq = msg & (1 << 31);
+
+ if (seq == mbx->seq_rcv) {
+ printk(KERN_ERR
+ "mbx: illegal seq bit! ignoring this command. "
+ "(%08x)\n", msg);
+ goto inc;
+ }
+ mbx->seq_rcv = seq;
+#endif
+
+ /* call receiver function */
+ if ((receiver = mbx->receiver_map[(msg >> 24) & 0x7f]) == NULL)
+ printk(KERN_ERR
+ "mbx: unknown message (%08x) received from "
+ "%s.\n", msg, mbx->name);
+ else
+ receiver(msg);
+
+#ifdef MBX_USE_SEQ_BIT
+inc:
+#endif
+ disable_newmsg_irq(mbx);
+ mbq_inc(mbq->rp);
+ if (mbq->rp == mbq->wp)
+ empty = 1;
+ /* if mbq has been full, now we have a room. */
+ if (mbq->full) {
+ mbq->full = 0;
+ enable_newmsg_irq(mbx);
+ }
+ enable_newmsg_irq(mbx);
+ }
+}
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t mbx_int_newmsg(int irq, void *p, struct pt_regs *regs)
+{
+ struct mbx *mbx = container_of(p, struct mbx, irq_devid_newmsg);
+ struct mbq *mbq = &mbx->mbq;
+ mbx_msg_t *msg;
+
+#ifdef CONFIG_ARCH_OMAP2
+ /*
+ * mailbox IRQ can be muxed.
+ * if it is not a newmsg interrupt, do nothing.
+ */
+ if (!has_newmsg_irq(mbx))
+ return IRQ_NONE;
+#endif
+
+ do {
+#ifdef CONFIG_ARCH_OMAP2
+ if (mbx_nomsg(mbx)) {
+ /* no more messages in the fifo. clear IRQ source. */
+ clear_newmsg_irq(mbx);
+ break;
+ }
+#endif
+
+ msg = &mbq->msg[mbq->wp];
+ read_mbx(mbx, msg);
+
+ mbq_inc(mbq->wp);
+ if (mbq->wp == mbq->rp) { /* mbq is full */
+ mbq->full = 1;
+ disable_newmsg_irq(mbx);
+ break;
+ }
+#if defined(CONFIG_ARCH_OMAP1)
+ } while (0); /* do it once */
+#elif defined(CONFIG_ARCH_OMAP2)
+ } while (1);
+#endif
+
+ schedule_work(&mbx->work);
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_ARCH_OMAP2
+static irqreturn_t mbx_int_notfull(int irq, void *p, struct pt_regs *regs)
+{
+ struct mbx *mbx = container_of(p, struct mbx, irq_devid_notfull);
+
+ /*
+ * mailbox IRQ can be muxed.
+ * if it is not a notfull interrupt, we do nothing.
+ */
+#if 0
+ if (!has_notfull_irq(mbx))
+#else
+ if (!(has_notfull_irq(mbx) && notfull_irq_enabled(mbx)))
+#endif
+ return IRQ_NONE;
+
+ disable_notfull_irq(mbx);
+
+#if 0 /*
+ * note: this doesn't seeem to work as explained in the manual.
+ * IRQSTATUS:NOTFULL can't be cleared even we write 1 to that bit.
+ * It is always set when it's not full, regardless of IRQENABLE setting.
+ */
+ clear_notfull_irq(mbx);
+#endif
+
+ wake_up_interruptible_all(&mbx->full_wait_q);
+ return IRQ_HANDLED;
+}
+#endif /* CONFIG_ARCH_OMAP2 */
+
+static int __init mbx_request_irq(struct mbx *mbx, const char *devname)
+{
+ int ret;
+
+#ifdef CONFIG_ARCH_OMAP2
+ enable_newmsg_irq(mbx);
+#endif
+
+ ret = request_irq(mbx->irq, mbx_int_newmsg, SA_INTERRUPT | SA_SHIRQ,
+ devname, &mbx->irq_devid_newmsg);
+ if (ret) {
+ printk(KERN_ERR
+ "failed to register DSP mailbox newmsg interrupt: "
+ "%d\n", ret);
+ return ret;
+ }
+
+#ifdef CONFIG_ARCH_OMAP2
+ ret = request_irq(mbx->irq, mbx_int_notfull, SA_INTERRUPT | SA_SHIRQ,
+ devname, &mbx->irq_devid_notfull);
+ if (ret) {
+ printk(KERN_ERR
+ "failed to register DSP mailbox notfull interrupt: "
+ "%d\n", ret);
+ return ret;
+ }
+#endif
+
+ return 0;
+}
+
+static int __init omap_mailbox_init(void)
+{
+ int ret;
+#ifdef CONFIG_ARCH_OMAP2
+ struct clk *mbx_ick_handle;
+#endif
+
+ printk(KERN_INFO "Initializing OMAP Mailboxes\n");
+#ifdef CONFIG_ARCH_OMAP2
+ /*
+ * FIXME: mbx_ick will never unsed
+ */
+ mbx_ick_handle = clk_get(NULL, "mailboxes_ick");
+ if (IS_ERR(mbx_ick_handle)) {
+ printk("Could not get mailboxes_ick\n");
+ return -ENODEV;
+ } else
+ clk_enable(mbx_ick_handle);
+#endif
+
+ if ((ret = mbx_request_irq(&mbx_dsp, "mbx_dsp")) != 0)
+ return ret;
+#ifdef CONFIG_ARCH_OMAP2
+ if ((ret = mbx_request_irq(&mbx_iva, "mbx_iva")) != 0)
+ return ret;
+#endif
+
+ return 0;
+}
+
+arch_initcall(omap_mailbox_init);
+
+EXPORT_SYMBOL(mbx_get);
+EXPORT_SYMBOL(mbx_send);
+EXPORT_SYMBOL(register_mbx_receiver);
+EXPORT_SYMBOL(unregister_mbx_receiver);
+EXPORT_SYMBOL(disable_mbx_irq);
+EXPORT_SYMBOL(enable_mbx_irq);
+EXPORT_SYMBOL(mbx_init_seq);
--- /dev/null
+/*
+ * Header for OMAP mailbox driver
+ *
+ * Copyright (C) 2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <asm/hardware.h>
+
+#if defined(CONFIG_ARCH_OMAP1)
+
+#define MAILBOX_BASE (0xfffcf000)
+#define MAILBOX_ARM2DSP1 (MAILBOX_BASE + 0x00)
+#define MAILBOX_ARM2DSP1b (MAILBOX_BASE + 0x04)
+#define MAILBOX_DSP2ARM1 (MAILBOX_BASE + 0x08)
+#define MAILBOX_DSP2ARM1b (MAILBOX_BASE + 0x0c)
+#define MAILBOX_DSP2ARM2 (MAILBOX_BASE + 0x10)
+#define MAILBOX_DSP2ARM2b (MAILBOX_BASE + 0x14)
+#define MAILBOX_ARM2DSP1_Flag (MAILBOX_BASE + 0x18)
+#define MAILBOX_DSP2ARM1_Flag (MAILBOX_BASE + 0x1c)
+#define MAILBOX_DSP2ARM2_Flag (MAILBOX_BASE + 0x20)
+
+#elif defined(CONFIG_ARCH_OMAP2)
+
+/*
+ * Mailbox: L4 peripheral -- use omap_readX(), omap_writeX()
+ */
+#define OMAP24XX_MAILBOX_BASE (L4_24XX_BASE + 0x94000)
+
+#define MAILBOX_REVISION (OMAP24XX_MAILBOX_BASE + 0x00)
+#define MAILBOX_SYSCONFIG (OMAP24XX_MAILBOX_BASE + 0x10)
+#define MAILBOX_SYSSTATUS (OMAP24XX_MAILBOX_BASE + 0x14)
+#define MAILBOX_MESSAGE_0 (OMAP24XX_MAILBOX_BASE + 0x40)
+#define MAILBOX_MESSAGE_1 (OMAP24XX_MAILBOX_BASE + 0x44)
+#define MAILBOX_MESSAGE_2 (OMAP24XX_MAILBOX_BASE + 0x48)
+#define MAILBOX_MESSAGE_3 (OMAP24XX_MAILBOX_BASE + 0x4c)
+#define MAILBOX_MESSAGE_4 (OMAP24XX_MAILBOX_BASE + 0x50)
+#define MAILBOX_MESSAGE_5 (OMAP24XX_MAILBOX_BASE + 0x54)
+#define MAILBOX_FIFOSTATUS_0 (OMAP24XX_MAILBOX_BASE + 0x80)
+#define MAILBOX_FIFOSTATUS_1 (OMAP24XX_MAILBOX_BASE + 0x84)
+#define MAILBOX_FIFOSTATUS_2 (OMAP24XX_MAILBOX_BASE + 0x88)
+#define MAILBOX_FIFOSTATUS_3 (OMAP24XX_MAILBOX_BASE + 0x8c)
+#define MAILBOX_FIFOSTATUS_4 (OMAP24XX_MAILBOX_BASE + 0x90)
+#define MAILBOX_FIFOSTATUS_5 (OMAP24XX_MAILBOX_BASE + 0x94)
+#define MAILBOX_MSGSTATUS_0 (OMAP24XX_MAILBOX_BASE + 0xc0)
+#define MAILBOX_MSGSTATUS_1 (OMAP24XX_MAILBOX_BASE + 0xc4)
+#define MAILBOX_MSGSTATUS_2 (OMAP24XX_MAILBOX_BASE + 0xc8)
+#define MAILBOX_MSGSTATUS_3 (OMAP24XX_MAILBOX_BASE + 0xcc)
+#define MAILBOX_MSGSTATUS_4 (OMAP24XX_MAILBOX_BASE + 0xd0)
+#define MAILBOX_MSGSTATUS_5 (OMAP24XX_MAILBOX_BASE + 0xd4)
+#define MAILBOX_IRQSTATUS_0 (OMAP24XX_MAILBOX_BASE + 0x100)
+#define MAILBOX_IRQENABLE_0 (OMAP24XX_MAILBOX_BASE + 0x104)
+#define MAILBOX_IRQSTATUS_1 (OMAP24XX_MAILBOX_BASE + 0x108)
+#define MAILBOX_IRQENABLE_1 (OMAP24XX_MAILBOX_BASE + 0x10c)
+#define MAILBOX_IRQSTATUS_2 (OMAP24XX_MAILBOX_BASE + 0x110)
+#define MAILBOX_IRQENABLE_2 (OMAP24XX_MAILBOX_BASE + 0x114)
+#define MAILBOX_IRQSTATUS_3 (OMAP24XX_MAILBOX_BASE + 0x118)
+#define MAILBOX_IRQENABLE_3 (OMAP24XX_MAILBOX_BASE + 0x11c)
+
+#define MAILBOX_IRQ_NOTFULL(n) (1<<(2*(n)+1))
+#define MAILBOX_IRQ_NEWMSG(n) (1<<(2*(n)))
+
+#endif /* CONFIG_ARCH_OMAP2 */
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-omap/dsp.h
- *
- * Header for OMAP DSP driver
- *
- * Copyright (C) 2002-2005 Nokia Corporation
- *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * 2005/06/01: DSP Gateway version 3.3
- */
-
-#ifndef ASM_ARCH_DSP_H
-#define ASM_ARCH_DSP_H
-
-
-/*
- * for /dev/dspctl/ctl
- */
-#define OMAP_DSP_IOCTL_RESET 1
-#define OMAP_DSP_IOCTL_RUN 2
-#define OMAP_DSP_IOCTL_SETRSTVECT 3
-#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
-#define OMAP_DSP_IOCTL_REGIOW 43
-#define OMAP_DSP_IOCTL_GETVAR 44
-#define OMAP_DSP_IOCTL_SETVAR 45
-#define OMAP_DSP_IOCTL_RUNLEVEL 50
-#define OMAP_DSP_IOCTL_SUSPEND 51
-#define OMAP_DSP_IOCTL_RESUME 52
-#define OMAP_DSP_IOCTL_FBEN 53
-#define OMAP_DSP_IOCTL_FBDIS 54
-#define OMAP_DSP_IOCTL_MBSEND 99
-
-/*
- * for taskdev
- * (ioctls below should be >= 0x10000)
- */
-#define OMAP_DSP_TASK_IOCTL_BFLSH 0x10000
-#define OMAP_DSP_TASK_IOCTL_SETBSZ 0x10001
-#define OMAP_DSP_TASK_IOCTL_LOCK 0x10002
-#define OMAP_DSP_TASK_IOCTL_UNLOCK 0x10003
-#define OMAP_DSP_TASK_IOCTL_GETNAME 0x10004
-
-/*
- * for /dev/dspctl/mem
- */
-#define OMAP_DSP_MEM_IOCTL_EXMAP 1
-#define OMAP_DSP_MEM_IOCTL_EXUNMAP 2
-#define OMAP_DSP_MEM_IOCTL_EXMAP_FLUSH 3
-#define OMAP_DSP_MEM_IOCTL_FBEXPORT 5
-#define OMAP_DSP_MEM_IOCTL_MMUITACK 7
-#define OMAP_DSP_MEM_IOCTL_MMUINIT 9
-#define OMAP_DSP_MEM_IOCTL_KMEM_RESERVE 11
-#define OMAP_DSP_MEM_IOCTL_KMEM_RELEASE 12
-
-struct omap_dsp_mapinfo {
- unsigned long dspadr;
- unsigned long size;
-};
-
-/*
- * for /dev/dspctl/twch
- */
-#define OMAP_DSP_TWCH_IOCTL_MKDEV 1
-#define OMAP_DSP_TWCH_IOCTL_RMDEV 2
-#define OMAP_DSP_TWCH_IOCTL_TADD 11
-#define OMAP_DSP_TWCH_IOCTL_TDEL 12
-#define OMAP_DSP_TWCH_IOCTL_TKILL 13
-
-#define OMAP_DSP_DEVSTATE_NOTASK 0x00000001
-#define OMAP_DSP_DEVSTATE_ATTACHED 0x00000002
-#define OMAP_DSP_DEVSTATE_GARBAGE 0x00000004
-#define OMAP_DSP_DEVSTATE_INVALID 0x00000008
-#define OMAP_DSP_DEVSTATE_ADDREQ 0x00000100
-#define OMAP_DSP_DEVSTATE_DELREQ 0x00000200
-#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;
- unsigned long taskadr;
-};
-#define OMAP_DSP_TADD_ABORTADR 0xffffffff
-
-
-/*
- * error cause definition (for error detection device)
- */
-#define OMAP_DSP_ERRDT_WDT 0x00000001
-#define OMAP_DSP_ERRDT_MMU 0x00000002
-
-
-/*
- * mailbox protocol definitions
- */
-
-struct omap_dsp_mailbox_cmd {
- unsigned short cmd;
- unsigned short data;
-};
-
-struct omap_dsp_reginfo {
- unsigned short adr;
- unsigned short val;
-};
-
-struct omap_dsp_varinfo {
- unsigned char varid;
- unsigned short val[0];
-};
-
-#define OMAP_DSP_MBPROT_REVISION 0x0019
-
-#define OMAP_DSP_MBCMD_WDSND 0x10
-#define OMAP_DSP_MBCMD_WDREQ 0x11
-#define OMAP_DSP_MBCMD_BKSND 0x20
-#define OMAP_DSP_MBCMD_BKREQ 0x21
-#define OMAP_DSP_MBCMD_BKYLD 0x23
-#define OMAP_DSP_MBCMD_BKSNDP 0x24
-#define OMAP_DSP_MBCMD_BKREQP 0x25
-#define OMAP_DSP_MBCMD_TCTL 0x30
-#define OMAP_DSP_MBCMD_TCTLDATA 0x31
-#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
-#define OMAP_DSP_MBCMD_KFUNC 0x54
-#define OMAP_DSP_MBCMD_TCFG 0x60
-#define OMAP_DSP_MBCMD_TADD 0x62
-#define OMAP_DSP_MBCMD_TDEL 0x63
-#define OMAP_DSP_MBCMD_TSTOP 0x65
-#define OMAP_DSP_MBCMD_DSPCFG 0x70
-#define OMAP_DSP_MBCMD_REGRW 0x72
-#define OMAP_DSP_MBCMD_GETVAR 0x74
-#define OMAP_DSP_MBCMD_SETVAR 0x75
-#define OMAP_DSP_MBCMD_ERR 0x78
-#define OMAP_DSP_MBCMD_DBG 0x79
-
-#define OMAP_DSP_MBCMD_TCTL_TINIT 0x0000
-#define OMAP_DSP_MBCMD_TCTL_TEN 0x0001
-#define OMAP_DSP_MBCMD_TCTL_TDIS 0x0002
-#define OMAP_DSP_MBCMD_TCTL_TCLR 0x0003
-#define OMAP_DSP_MBCMD_TCTL_TCLR_FORCE 0x0004
-
-#define OMAP_DSP_MBCMD_RUNLEVEL_USER 0x01
-#define OMAP_DSP_MBCMD_RUNLEVEL_SUPER 0x0e
-#define OMAP_DSP_MBCMD_RUNLEVEL_RECOVERY 0x10
-
-#define OMAP_DSP_MBCMD_PM_DISABLE 0x00
-#define OMAP_DSP_MBCMD_PM_ENABLE 0x01
-
-#define OMAP_DSP_MBCMD_KFUNC_FBCTL 0x00
-#define OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR 0x01
-
-#define OMAP_DSP_MBCMD_FBCTL_UPD 0x0000
-#define OMAP_DSP_MBCMD_FBCTL_ENABLE 0x0002
-#define OMAP_DSP_MBCMD_FBCTL_DISABLE 0x0003
-
-#define OMAP_DSP_MBCMD_AUDIO_PWR_UP 0x0000
-#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN1 0x0001
-#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN2 0x0002
-
-#define OMAP_DSP_MBCMD_TDEL_SAFE 0x0000
-#define OMAP_DSP_MBCMD_TDEL_KILL 0x0001
-
-#define OMAP_DSP_MBCMD_DSPCFG_REQ 0x00
-#define OMAP_DSP_MBCMD_DSPCFG_SYSADRH 0x28
-#define OMAP_DSP_MBCMD_DSPCFG_SYSADRL 0x29
-#define OMAP_DSP_MBCMD_DSPCFG_PROTREV 0x70
-#define OMAP_DSP_MBCMD_DSPCFG_ABORT 0x78
-#define OMAP_DSP_MBCMD_DSPCFG_LAST 0x80
-
-#define OMAP_DSP_MBCMD_REGRW_MEMR 0x00
-#define OMAP_DSP_MBCMD_REGRW_MEMW 0x01
-#define OMAP_DSP_MBCMD_REGRW_IOR 0x02
-#define OMAP_DSP_MBCMD_REGRW_IOW 0x03
-#define OMAP_DSP_MBCMD_REGRW_DATA 0x04
-
-#define OMAP_DSP_MBCMD_VARID_ICRMASK 0x00
-#define OMAP_DSP_MBCMD_VARID_LOADINFO 0x01
-
-#define OMAP_DSP_TTYP_ARCV 0x0001
-#define OMAP_DSP_TTYP_ASND 0x0002
-#define OMAP_DSP_TTYP_BKMD 0x0004
-#define OMAP_DSP_TTYP_BKDM 0x0008
-#define OMAP_DSP_TTYP_PVMD 0x0010
-#define OMAP_DSP_TTYP_PVDM 0x0020
-
-#define OMAP_DSP_EID_BADTID 0x10
-#define OMAP_DSP_EID_BADTCN 0x11
-#define OMAP_DSP_EID_BADBID 0x20
-#define OMAP_DSP_EID_BADCNT 0x21
-#define OMAP_DSP_EID_NOTLOCKED 0x22
-#define OMAP_DSP_EID_STVBUF 0x23
-#define OMAP_DSP_EID_BADADR 0x24
-#define OMAP_DSP_EID_BADTCTL 0x30
-#define OMAP_DSP_EID_BADPARAM 0x50
-#define OMAP_DSP_EID_FATAL 0x58
-#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
-#define OMAP_DSP_EID_BADCFGTYP 0xf0
-#define OMAP_DSP_EID_DEBUG 0xf8
-#define OMAP_DSP_EID_BADSEQ 0xfe
-#define OMAP_DSP_EID_BADCMD 0xff
-
-#define OMAP_DSP_TNM_LEN 16
-
-#define OMAP_DSP_TID_FREE 0xff
-#define OMAP_DSP_TID_ANON 0xfe
-
-#define OMAP_DSP_BID_NULL 0xffff
-#define OMAP_DSP_BID_PVT 0xfffe
-
-#endif /* ASM_ARCH_DSP_H */
/*
- * linux/include/asm-arm/arch-omap/dsp_common.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
*
- * Header for OMAP DSP subsystem control
+ * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
*
- * Copyright (C) 2004,2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*
- * 2005/06/03: DSP Gateway version 3.3
*/
#ifndef ASM_ARCH_DSP_COMMON_H
#define ASM_ARCH_DSP_COMMON_H
+#ifdef CONFIG_ARCH_OMAP1
extern void omap_dsp_request_mpui(void);
extern void omap_dsp_release_mpui(void);
extern int omap_dsp_request_mem(void);
extern int omap_dsp_release_mem(void);
+#endif
extern void (*omap_dsp_audio_pwr_up_request)(int stage);
extern void (*omap_dsp_audio_pwr_down_request)(int stage);
#define io_p2v(pa) ((pa) + IO_OFFSET) /* Works for L3 and L4 */
#define io_v2p(va) ((va) - IO_OFFSET) /* Works for L3 and L4 */
+/* DSP */
+#define DSP_MEM_24XX_PHYS OMAP24XX_DSP_MEM_BASE /* 0x58000000 */
+#define DSP_MEM_24XX_VIRT 0xe0000000
+#define DSP_MEM_24XX_SIZE 0x28000
+#define DSP_IPI_24XX_PHYS OMAP24XX_DSP_IPI_BASE /* 0x59000000 */
+#define DSP_IPI_24XX_VIRT 0xe1000000
+#define DSP_IPI_24XX_SIZE SZ_4K
+#define DSP_MMU_24XX_PHYS OMAP24XX_DSP_MMU_BASE /* 0x5a000000 */
+#define DSP_MMU_24XX_VIRT 0xe2000000
+#define DSP_MMU_24XX_SIZE SZ_4K
+
#endif
#ifndef __ASSEMBLER__
#define INT_DSP_MMU_ABORT 7
#define INT_HOST 8
#define INT_ABORT 9
-#define INT_DSP_MAILBOX1 10
-#define INT_DSP_MAILBOX2 11
#define INT_BRIDGE_PRIV 13
#define INT_GPIO_BANK1 14
#define INT_UART3 15
#define INT_1510_RES2 2
#define INT_1510_SPI_TX 4
#define INT_1510_SPI_RX 5
+#define INT_1510_DSP_MAILBOX1 10
+#define INT_1510_DSP_MAILBOX2 11
#define INT_1510_RES12 12
#define INT_1510_LB_MMU 17
#define INT_1510_RES18 18
#define INT_1610_IH2_FIQ 2
#define INT_1610_McBSP2_TX 4
#define INT_1610_McBSP2_RX 5
+#define INT_1610_DSP_MAILBOX1 10
+#define INT_1610_DSP_MAILBOX2 11
#define INT_1610_LCD_LINE 12
#define INT_1610_GPTIMER1 17
#define INT_1610_GPTIMER2 18
#define INT_RTC_TIMER (25 + IH2_BASE)
#define INT_RTC_ALARM (26 + IH2_BASE)
#define INT_MEM_STICK (27 + IH2_BASE)
-#define INT_DSP_MMU (28 + IH2_BASE)
/*
* OMAP-1510 specific IRQ numbers for interrupt handler 2
*/
+#define INT_1510_DSP_MMU (28 + IH2_BASE)
#define INT_1510_COM_SPI_RO (31 + IH2_BASE)
/*
#define INT_1610_USB_OTG (8 + IH2_BASE)
#define INT_1610_SoSSI (9 + IH2_BASE)
#define INT_1610_SoSSI_MATCH (19 + IH2_BASE)
+#define INT_1610_DSP_MMU (28 + IH2_BASE)
#define INT_1610_McBSP2RX_OF (31 + IH2_BASE)
#define INT_1610_STI (32 + IH2_BASE)
#define INT_1610_STI_WAKEUP (33 + IH2_BASE)
#define INT_24XX_SDMA_IRQ3 15
#define INT_24XX_CAM_IRQ 24
#define INT_24XX_DSS_IRQ 25
+#define INT_24XX_MAIL_U0_MPU 26
+#define INT_24XX_DSP_UMA 27
+#define INT_24XX_DSP_MMU 28
#define INT_24XX_GPIO_BANK1 29
#define INT_24XX_GPIO_BANK2 30
#define INT_24XX_GPIO_BANK3 31
#define INT_24XX_GPIO_BANK4 32
+#define INT_24XX_MAIL_U3_MPU 34
#define INT_24XX_GPTIMER1 37
#define INT_24XX_GPTIMER2 38
#define INT_24XX_GPTIMER3 39
--- /dev/null
+/* mailbox.h */
+
+#ifndef MAILBOX_H
+#define MAILBOX_H
+
+typedef u32 mbx_msg_t;
+typedef void (mbx_receiver_t)(mbx_msg_t msg);
+
+struct mbx; /* contents are private */
+
+struct mbx *mbx_get(const char *id);
+extern int mbx_send(struct mbx *mbx_h, mbx_msg_t msg);
+extern int register_mbx_receiver(struct mbx *mbx, unsigned char cmd,
+ mbx_receiver_t *rcv);
+extern int unregister_mbx_receiver(struct mbx *mbx, unsigned char cmd,
+ mbx_receiver_t *rcv);
+extern void enable_mbx_irq(struct mbx *mbx);
+extern void disable_mbx_irq(struct mbx *mbx);
+extern void mbx_init_seq(struct mbx *mbx);
+
+/*
+ * mailbox command: 0x00 - 0x7f
+ * when a driver wants to use mailbox, it must reserve mailbox commands here.
+ */
+#define MBX_CMD_MAX 0x80
+
+/* DSP Gateway */
+#define MBX_CMD_DSP_WDSND 0x10
+#define MBX_CMD_DSP_WDREQ 0x11
+#define MBX_CMD_DSP_BKSND 0x20
+#define MBX_CMD_DSP_BKREQ 0x21
+#define MBX_CMD_DSP_BKYLD 0x23
+#define MBX_CMD_DSP_BKSNDP 0x24
+#define MBX_CMD_DSP_BKREQP 0x25
+#define MBX_CMD_DSP_TCTL 0x30
+#define MBX_CMD_DSP_TCTLDATA 0x31
+#define MBX_CMD_DSP_POLL 0x32
+#define MBX_CMD_DSP_WDT 0x50
+#define MBX_CMD_DSP_RUNLEVEL 0x51
+#define MBX_CMD_DSP_PM 0x52
+#define MBX_CMD_DSP_SUSPEND 0x53
+#define MBX_CMD_DSP_KFUNC 0x54
+#define MBX_CMD_DSP_TCFG 0x60
+#define MBX_CMD_DSP_TADD 0x62
+#define MBX_CMD_DSP_TDEL 0x63
+#define MBX_CMD_DSP_TSTOP 0x65
+#define MBX_CMD_DSP_DSPCFG 0x70
+#define MBX_CMD_DSP_REGRW 0x72
+#define MBX_CMD_DSP_GETVAR 0x74
+#define MBX_CMD_DSP_SETVAR 0x75
+#define MBX_CMD_DSP_ERR 0x78
+#define MBX_CMD_DSP_DBG 0x79
+
+#endif /* MAILBOX_H */
#define OMAP242X_CONTROL_STATUS (L4_24XX_BASE + 0x2f8)
+/* DSP SS */
+#define OMAP24XX_DSP_BASE 0x58000000
+#define OMAP24XX_DSP_MEM_BASE (OMAP24XX_DSP_BASE + 0x0)
+#define OMAP24XX_DSP_IPI_BASE (OMAP24XX_DSP_BASE + 0x1000000)
+#define OMAP24XX_DSP_MMU_BASE (OMAP24XX_DSP_BASE + 0x2000000)
+
#endif /* __ASM_ARCH_OMAP24XX_H */