]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/dsp/mblog.c
53ac4aede5e047c67fbb2d95bfdb37be1f785e03
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / dsp / mblog.c
1 /*
2  * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
3  *
4  * Copyright (C) 2003-2006 Nokia Corporation. All rights reserved.
5  *
6  * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
7  *
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.
11  *
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.
16  *
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
20  * 02110-1301 USA
21  *
22  */
23
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"
29 #include "dsp.h"
30
31 char *subcmd_name(struct mbcmd *mb)
32 {
33         u8 cmd_h = mb->cmd_h;
34         u8 cmd_l = mb->cmd_l;
35         char *s;
36
37         switch (cmd_h) {
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":
42                     NULL;
43                 break;
44         case MBOX_CMD_DSP_PM:
45                 s = (cmd_l == PM_DISABLE) ? "DISABLE":
46                     (cmd_l == PM_ENABLE)  ? "ENABLE":
47                     NULL;
48                 break;
49         case MBOX_CMD_DSP_KFUNC:
50                 s = (cmd_l == KFUNC_FBCTL) ? "FBCTL":
51                     (cmd_l == KFUNC_POWER) ? "POWER":
52                     NULL;
53                 break;
54         case MBOX_CMD_DSP_DSPCFG:
55                 {
56                         u8 cfgc = cmd_l & 0x7f;
57                         s = (cfgc == DSPCFG_REQ)     ? "REQ":
58                             (cfgc == DSPCFG_SYSADRH) ? "SYSADRH":
59                             (cfgc == DSPCFG_SYSADRL) ? "SYSADRL":
60                             (cfgc == DSPCFG_ABORT)   ? "ABORT":
61                             (cfgc == DSPCFG_PROTREV) ? "PROTREV":
62                             NULL;
63                         break;
64                 }
65         case MBOX_CMD_DSP_REGRW:
66                 s = (cmd_l == REGRW_MEMR) ? "MEMR":
67                     (cmd_l == REGRW_MEMW) ? "MEMW":
68                     (cmd_l == REGRW_IOR)  ? "IOR":
69                     (cmd_l == REGRW_IOW)  ? "IOW":
70                     (cmd_l == REGRW_DATA) ? "DATA":
71                     NULL;
72                 break;
73         case MBOX_CMD_DSP_GETVAR:
74         case MBOX_CMD_DSP_SETVAR:
75                 s = (cmd_l == VARID_ICRMASK)  ? "ICRMASK":
76                     (cmd_l == VARID_LOADINFO) ? "LOADINFO":
77                     NULL;
78                 break;
79         case MBOX_CMD_DSP_ERR:
80                 s = (cmd_l == EID_BADTID)     ? "BADTID":
81                     (cmd_l == EID_BADTCN)     ? "BADTCN":
82                     (cmd_l == EID_BADBID)     ? "BADBID":
83                     (cmd_l == EID_BADCNT)     ? "BADCNT":
84                     (cmd_l == EID_NOTLOCKED)  ? "NOTLOCKED":
85                     (cmd_l == EID_STVBUF)     ? "STVBUF":
86                     (cmd_l == EID_BADADR)     ? "BADADR":
87                     (cmd_l == EID_BADTCTL)    ? "BADTCTL":
88                     (cmd_l == EID_BADPARAM)   ? "BADPARAM":
89                     (cmd_l == EID_FATAL)      ? "FATAL":
90                     (cmd_l == EID_WDT)        ? "WDT":
91                     (cmd_l == EID_NOMEM)      ? "NOMEM":
92                     (cmd_l == EID_NORES)      ? "NORES":
93                     (cmd_l == EID_IPBFULL)    ? "IPBFULL":
94                     (cmd_l == EID_TASKNOTRDY) ? "TASKNOTRDY":
95                     (cmd_l == EID_TASKBSY)    ? "TASKBSY":
96                     (cmd_l == EID_TASKERR)    ? "TASKERR":
97                     (cmd_l == EID_BADCFGTYP)  ? "BADCFGTYP":
98                     (cmd_l == EID_DEBUG)      ? "DEBUG":
99                     (cmd_l == EID_BADSEQ)     ? "BADSEQ":
100                     (cmd_l == EID_BADCMD)     ? "BADCMD":
101                     NULL;
102                 break;
103         default:
104                 s = NULL;
105         }
106
107         return s;
108 }
109
110 /* output of show() method should fit to PAGE_SIZE */
111 #define MBLOG_DEPTH     64
112
113 struct mblogent {
114         unsigned long jiffies;
115         mbox_msg_t msg;
116         arm_dsp_dir_t dir;
117 };
118
119 static struct {
120         spinlock_t lock;
121         int wp;
122         unsigned long cnt, cnt_ad, cnt_da;
123         struct mblogent ent[MBLOG_DEPTH];
124 } mblog = {
125         .lock = SPIN_LOCK_UNLOCKED,
126 };
127
128 #ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
129 static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir)
130 {
131         const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
132         char *dir_str;
133         char *subname;
134
135         dir_str = (dir == DIR_A2D) ? "sending  " : "receiving";
136         switch (ci->cmd_l_type) {
137         case CMD_L_TYPE_SUBCMD:
138                 subname = subcmd_name(mb);
139                 if (unlikely(!subname))
140                         subname = "Unknown";
141                 printk(KERN_DEBUG
142                        "mbox: %s seq=%d, cmd=%02x:%02x(%s:%s), data=%04x\n",
143                        dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
144                        ci->name, subname, mb->data);
145                 break;
146         case CMD_L_TYPE_TID:
147                 printk(KERN_DEBUG
148                        "mbox: %s seq=%d, cmd=%02x:%02x(%s:task %d), data=%04x\n",
149                        dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
150                        ci->name, mb->cmd_l, mb->data);
151                 break;
152         case CMD_L_TYPE_NULL:
153                 printk(KERN_DEBUG
154                        "mbox: %s seq=%d, cmd=%02x:%02x(%s), data=%04x\n",
155                        dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
156                        ci->name, mb->data);
157                 break;
158         }
159 }
160 #else
161 static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir) { }
162 #endif
163
164 void mblog_add(struct mbcmd *mb, arm_dsp_dir_t dir)
165 {
166         struct mblogent *ent;
167
168         spin_lock(&mblog.lock);
169         ent = &mblog.ent[mblog.wp];
170         ent->jiffies = jiffies;
171         ent->msg = *(mbox_msg_t *)mb;
172         ent->dir = dir;
173         if (mblog.cnt < 0xffffffff)
174                 mblog.cnt++;
175         switch (dir) {
176         case DIR_A2D:
177                 if (mblog.cnt_ad < 0xffffffff)
178                         mblog.cnt_ad++;
179                 break;
180         case DIR_D2A:
181                 if (mblog.cnt_da < 0xffffffff)
182                         mblog.cnt_da++;
183                 break;
184         }
185         if (++mblog.wp == MBLOG_DEPTH)
186                 mblog.wp = 0;
187         spin_unlock(&mblog.lock);
188
189         mblog_print_cmd(mb, dir);
190 }
191
192 /*
193  * sysfs file
194  */
195 static ssize_t mblog_show(struct device *dev, struct device_attribute *attr,
196                           char *buf)
197 {
198         int len = 0;
199         int wp;
200         int i;
201
202         spin_lock(&mblog.lock);
203
204         wp = mblog.wp;
205         len += sprintf(buf + len,
206                        "log count:%ld / ARM->DSP:%ld, DSP->ARM:%ld\n",
207                        mblog.cnt, mblog.cnt_ad, mblog.cnt_da);
208         if (mblog.cnt == 0)
209                 goto done;
210
211         len += sprintf(buf + len, "           ARM->DSP   ARM<-DSP\n");
212         len += sprintf(buf + len, " jiffies  cmd  data  cmd  data\n");
213         i = (mblog.cnt >= MBLOG_DEPTH) ? wp : 0;
214         do {
215                 struct mblogent *ent = &mblog.ent[i];
216                 struct mbcmd *mb = (struct mbcmd *)&ent->msg;
217                 char *subname;
218                 struct cmdinfo ci_null = {
219                         .name = "Unknown",
220                         .cmd_l_type = CMD_L_TYPE_NULL,
221                 };
222                 const struct cmdinfo *ci;
223
224                 len += sprintf(buf + len,
225                                (ent->dir == DIR_A2D) ?
226                                 "%08lx  %04x %04x            ":
227                                 "%08lx             %04x %04x ",
228                                ent->jiffies,
229                                (ent->msg >> 16) & 0x7fff, ent->msg & 0xffff);
230
231                 if ((ci = cmdinfo[mb->cmd_h]) == NULL)
232                         ci = &ci_null;
233
234                 switch (ci->cmd_l_type) {
235                 case CMD_L_TYPE_SUBCMD:
236                         if ((subname = subcmd_name(mb)) == NULL)
237                                 subname = "Unknown";
238                         len += sprintf(buf + len, "%s:%s\n",
239                                        ci->name, subname);
240                         break;
241                 case CMD_L_TYPE_TID:
242                         len += sprintf(buf + len, "%s:task %d\n",
243                                        ci->name, mb->cmd_l);
244                         break;
245                 case CMD_L_TYPE_NULL:
246                         len += sprintf(buf + len, "%s\n", ci->name);
247                         break;
248                 }
249
250                 if (++i == MBLOG_DEPTH)
251                         i = 0;
252         } while (i != wp);
253
254 done:
255         spin_unlock(&mblog.lock);
256
257         return len;
258 }
259
260 static struct device_attribute dev_attr_mblog = __ATTR_RO(mblog);
261
262 void __init mblog_init(void)
263 {
264         int ret;
265
266         ret = device_create_file(omap_dsp->dev, &dev_attr_mblog);
267         if (ret)
268                 printk(KERN_ERR "device_create_file failed: %d\n", ret);
269 }
270
271 void mblog_exit(void)
272 {
273         device_remove_file(omap_dsp->dev, &dev_attr_mblog);
274 }