2 * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
4 * Copyright (C) 2003-2006 Nokia Corporation. All rights reserved.
6 * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 #include <linux/platform_device.h>
25 #include <linux/init.h>
26 #include <linux/jiffies.h>
27 #include <asm/arch/mailbox.h>
28 #include "dsp_mbcmd.h"
31 char *subcmd_name(struct mbcmd *mb)
38 case MBOX_CMD_DSP_RUNLEVEL:
39 s = (cmd_l == RUNLEVEL_USER) ? "USER":
40 (cmd_l == RUNLEVEL_SUPER) ? "SUPER":
41 (cmd_l == RUNLEVEL_RECOVERY) ? "RECOVERY":
45 s = (cmd_l == PM_DISABLE) ? "DISABLE":
46 (cmd_l == PM_ENABLE) ? "ENABLE":
49 case MBOX_CMD_DSP_KFUNC:
50 s = (cmd_l == KFUNC_FBCTL) ? "FBCTL":
51 (cmd_l == KFUNC_POWER) ?
52 ((mb->data == AUDIO_PWR_UP) ? "PWR AUD /UP":
53 (mb->data == AUDIO_PWR_DOWN) ? "PWR AUD /DOWN":
54 (mb->data == AUDIO_PWR_DOWN2) ? "PWR AUD /DOWN(2)":
55 (mb->data == DSP_PWR_UP) ? "PWR DSP /UP":
56 (mb->data == DSP_PWR_DOWN) ? "PWR DSP /DOWN":
57 (mb->data == DVFS_START) ? "PWR DVFS/START":
58 (mb->data == DVFS_STOP) ? "PWR DVFS/STOP":
63 case MBOX_CMD_DSP_DSPCFG:
65 u8 cfgc = cmd_l & 0x7f;
66 s = (cfgc == DSPCFG_REQ) ? "REQ":
67 (cfgc == DSPCFG_SYSADRH) ? "SYSADRH":
68 (cfgc == DSPCFG_SYSADRL) ? "SYSADRL":
69 (cfgc == DSPCFG_ABORT) ? "ABORT":
70 (cfgc == DSPCFG_PROTREV) ? "PROTREV":
74 case MBOX_CMD_DSP_REGRW:
75 s = (cmd_l == REGRW_MEMR) ? "MEMR":
76 (cmd_l == REGRW_MEMW) ? "MEMW":
77 (cmd_l == REGRW_IOR) ? "IOR":
78 (cmd_l == REGRW_IOW) ? "IOW":
79 (cmd_l == REGRW_DATA) ? "DATA":
82 case MBOX_CMD_DSP_GETVAR:
83 case MBOX_CMD_DSP_SETVAR:
84 s = (cmd_l == VARID_ICRMASK) ? "ICRMASK":
85 (cmd_l == VARID_LOADINFO) ? "LOADINFO":
88 case MBOX_CMD_DSP_ERR:
89 s = (cmd_l == EID_BADTID) ? "BADTID":
90 (cmd_l == EID_BADTCN) ? "BADTCN":
91 (cmd_l == EID_BADBID) ? "BADBID":
92 (cmd_l == EID_BADCNT) ? "BADCNT":
93 (cmd_l == EID_NOTLOCKED) ? "NOTLOCKED":
94 (cmd_l == EID_STVBUF) ? "STVBUF":
95 (cmd_l == EID_BADADR) ? "BADADR":
96 (cmd_l == EID_BADTCTL) ? "BADTCTL":
97 (cmd_l == EID_BADPARAM) ? "BADPARAM":
98 (cmd_l == EID_FATAL) ? "FATAL":
99 (cmd_l == EID_WDT) ? "WDT":
100 (cmd_l == EID_NOMEM) ? "NOMEM":
101 (cmd_l == EID_NORES) ? "NORES":
102 (cmd_l == EID_IPBFULL) ? "IPBFULL":
103 (cmd_l == EID_TASKNOTRDY) ? "TASKNOTRDY":
104 (cmd_l == EID_TASKBSY) ? "TASKBSY":
105 (cmd_l == EID_TASKERR) ? "TASKERR":
106 (cmd_l == EID_BADCFGTYP) ? "BADCFGTYP":
107 (cmd_l == EID_DEBUG) ? "DEBUG":
108 (cmd_l == EID_BADSEQ) ? "BADSEQ":
109 (cmd_l == EID_BADCMD) ? "BADCMD":
119 /* output of show() method should fit to PAGE_SIZE */
120 #define MBLOG_DEPTH 64
123 unsigned long jiffies;
131 unsigned long cnt, cnt_ad, cnt_da;
132 struct mblogent ent[MBLOG_DEPTH];
134 .lock = SPIN_LOCK_UNLOCKED,
137 #ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
138 static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir)
140 const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
144 dir_str = (dir == DIR_A2D) ? "sending " : "receiving";
145 switch (ci->cmd_l_type) {
146 case CMD_L_TYPE_SUBCMD:
147 subname = subcmd_name(mb);
148 if (unlikely(!subname))
150 pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s:%s), data=%04x\n",
151 dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
152 ci->name, subname, mb->data);
155 pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s:task %d), data=%04x\n",
156 dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
157 ci->name, mb->cmd_l, mb->data);
159 case CMD_L_TYPE_NULL:
160 pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s), data=%04x\n",
161 dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
167 static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir) { }
170 void mblog_add(struct mbcmd *mb, arm_dsp_dir_t dir)
172 struct mblogent *ent;
174 spin_lock(&mblog.lock);
175 ent = &mblog.ent[mblog.wp];
176 ent->jiffies = jiffies;
177 ent->msg = *(mbox_msg_t *)mb;
179 if (mblog.cnt < 0xffffffff)
183 if (mblog.cnt_ad < 0xffffffff)
187 if (mblog.cnt_da < 0xffffffff)
191 if (++mblog.wp == MBLOG_DEPTH)
193 spin_unlock(&mblog.lock);
195 mblog_print_cmd(mb, dir);
201 static ssize_t mblog_show(struct device *dev, struct device_attribute *attr,
208 spin_lock(&mblog.lock);
211 len += sprintf(buf + len,
212 "log count:%ld / ARM->DSP:%ld, DSP->ARM:%ld\n",
213 mblog.cnt, mblog.cnt_ad, mblog.cnt_da);
217 len += sprintf(buf + len, " ARM->DSP ARM<-DSP\n");
218 len += sprintf(buf + len, " jiffies cmd data cmd data\n");
219 i = (mblog.cnt >= MBLOG_DEPTH) ? wp : 0;
221 struct mblogent *ent = &mblog.ent[i];
222 struct mbcmd *mb = (struct mbcmd *)&ent->msg;
224 struct cmdinfo ci_null = {
226 .cmd_l_type = CMD_L_TYPE_NULL,
228 const struct cmdinfo *ci;
230 len += sprintf(buf + len,
231 (ent->dir == DIR_A2D) ?
235 (ent->msg >> 16) & 0x7fff, ent->msg & 0xffff);
237 if ((ci = cmdinfo[mb->cmd_h]) == NULL)
240 switch (ci->cmd_l_type) {
241 case CMD_L_TYPE_SUBCMD:
242 if ((subname = subcmd_name(mb)) == NULL)
244 len += sprintf(buf + len, "%s:%s\n",
248 len += sprintf(buf + len, "%s:task %d\n",
249 ci->name, mb->cmd_l);
251 case CMD_L_TYPE_NULL:
252 len += sprintf(buf + len, "%s\n", ci->name);
256 if (++i == MBLOG_DEPTH)
261 spin_unlock(&mblog.lock);
266 static struct device_attribute dev_attr_mblog = __ATTR_RO(mblog);
268 void __init mblog_init(void)
272 ret = device_create_file(omap_dsp->dev, &dev_attr_mblog);
274 printk(KERN_ERR "device_create_file failed: %d\n", ret);
277 void mblog_exit(void)
279 device_remove_file(omap_dsp->dev, &dev_attr_mblog);