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