]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/dsp/mblog.c
Merge with /home/tmlind/src/kernel/linux-2.6
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / dsp / mblog.c
1 /*
2  * linux/arch/arm/mach-omap/dsp/mblog.c
3  *
4  * OMAP DSP driver Mailbox log module
5  *
6  * Copyright (C) 2003-2005 Nokia Corporation
7  *
8  * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23  *
24  * 2005/05/18:  DSP Gateway version 3.3
25  */
26
27 #include <linux/module.h>
28 #include <linux/sched.h>
29 #include <linux/platform_device.h>
30 #include <linux/init.h>
31 #include <asm/irq.h>
32 #include <asm/arch/dsp.h>
33 #include "dsp.h"
34
35 #define RLCMD(nm)       OMAP_DSP_MBCMD_RUNLEVEL_##nm
36 #define KFUNCCMD(nm)    OMAP_DSP_MBCMD_KFUNC_##nm
37 #define PMCMD(nm)       OMAP_DSP_MBCMD_PM_##nm
38 #define CFGCMD(nm)      OMAP_DSP_MBCMD_DSPCFG_##nm
39 #define REGCMD(nm)      OMAP_DSP_MBCMD_REGRW_##nm
40 #define VICMD(nm)       OMAP_DSP_MBCMD_VARID_##nm
41 #define EID(nm)         OMAP_DSP_EID_##nm
42
43 char *subcmd_name(struct mbcmd *mb)
44 {
45         unsigned char cmd_h = mb->cmd_h;
46         unsigned char cmd_l = mb->cmd_l;
47         char *s;
48
49         switch (cmd_h) {
50         case MBCMD(RUNLEVEL):
51                 s = (cmd_l == RLCMD(USER))     ? "USER":
52                     (cmd_l == RLCMD(SUPER))    ? "SUPER":
53                     (cmd_l == RLCMD(RECOVERY)) ? "RECOVERY":
54                     NULL;
55                 break;
56         case MBCMD(PM):
57                 s = (cmd_l == PMCMD(DISABLE)) ? "DISABLE":
58                     (cmd_l == PMCMD(ENABLE))  ? "ENABLE":
59                     NULL;
60                 break;
61         case MBCMD(KFUNC):
62                 s = (cmd_l == KFUNCCMD(FBCTL))     ? "FBCTL":
63                     (cmd_l == KFUNCCMD(AUDIO_PWR)) ? "AUDIO_PWR":
64                     NULL;
65                 break;
66         case MBCMD(DSPCFG):
67                 {
68                         unsigned char cfgc = cmd_l & 0x7f;
69                         s = (cfgc == CFGCMD(REQ))     ? "REQ":
70                             (cfgc == CFGCMD(SYSADRH)) ? "SYSADRH":
71                             (cfgc == CFGCMD(SYSADRL)) ? "SYSADRL":
72                             (cfgc == CFGCMD(ABORT))   ? "ABORT":
73                             (cfgc == CFGCMD(PROTREV)) ? "PROTREV":
74                             NULL;
75                         break;
76                 }
77         case MBCMD(REGRW):
78                 s = (cmd_l == REGCMD(MEMR)) ? "MEMR":
79                     (cmd_l == REGCMD(MEMW)) ? "MEMW":
80                     (cmd_l == REGCMD(IOR))  ? "IOR":
81                     (cmd_l == REGCMD(IOW))  ? "IOW":
82                     (cmd_l == REGCMD(DATA)) ? "DATA":
83                     NULL;
84                 break;
85         case MBCMD(GETVAR):
86         case MBCMD(SETVAR):
87                 s = (cmd_l == VICMD(ICRMASK))  ? "ICRMASK":
88                     (cmd_l == VICMD(LOADINFO)) ? "LOADINFO":
89                     NULL;
90                 break;
91         case MBCMD(ERR):
92                 s = (cmd_l == EID(BADTID))     ? "BADTID":
93                     (cmd_l == EID(BADTCN))     ? "BADTCN":
94                     (cmd_l == EID(BADBID))     ? "BADBID":
95                     (cmd_l == EID(BADCNT))     ? "BADCNT":
96                     (cmd_l == EID(NOTLOCKED))  ? "NOTLOCKED":
97                     (cmd_l == EID(STVBUF))     ? "STVBUF":
98                     (cmd_l == EID(BADADR))     ? "BADADR":
99                     (cmd_l == EID(BADTCTL))    ? "BADTCTL":
100                     (cmd_l == EID(BADPARAM))   ? "BADPARAM":
101                     (cmd_l == EID(FATAL))      ? "FATAL":
102                     (cmd_l == EID(WDT))        ? "WDT":
103                     (cmd_l == EID(NOMEM))      ? "NOMEM":
104                     (cmd_l == EID(NORES))      ? "NORES":
105                     (cmd_l == EID(IPBFULL))    ? "IPBFULL":
106                     (cmd_l == EID(TASKNOTRDY)) ? "TASKNOTRDY":
107                     (cmd_l == EID(TASKBSY))    ? "TASKBSY":
108                     (cmd_l == EID(TASKERR))    ? "TASKERR":
109                     (cmd_l == EID(BADCFGTYP))  ? "BADCFGTYP":
110                     (cmd_l == EID(DEBUG))      ? "DEBUG":
111                     (cmd_l == EID(BADSEQ))     ? "BADSEQ":
112                     (cmd_l == EID(BADCMD))     ? "BADCMD":
113                     NULL;
114                 break;
115         default:
116                 s = NULL;
117         }
118
119         return s;
120 }
121
122 /* output of show() method should fit to PAGE_SIZE */
123 #define MBLOG_DEPTH     64
124
125 struct mblogent {
126         unsigned long jiffies;
127         unsigned short cmd;
128         unsigned short data;
129         enum arm_dsp_dir dir;
130 };
131
132 static struct {
133         spinlock_t lock;
134         int wp;
135         unsigned long cnt, cnt_ad, cnt_da;
136         struct mblogent ent[MBLOG_DEPTH];
137 } mblog;
138
139 void mblog_add(struct mbcmd *mb, enum arm_dsp_dir dir)
140 {
141         struct mbcmd_hw *mb_hw = (struct mbcmd_hw *)mb;
142         struct mblogent *ent;
143
144         spin_lock(&mblog.lock);
145         ent = &mblog.ent[mblog.wp];
146         ent->jiffies = jiffies;
147         ent->cmd     = mb_hw->cmd;
148         ent->data    = mb_hw->data;
149         ent->dir     = dir;
150         if (mblog.cnt < 0xffffffff)
151                 mblog.cnt++;
152         switch (dir) {
153         case DIR_A2D:
154                 if (mblog.cnt_ad < 0xffffffff)
155                         mblog.cnt_ad++;
156                 break;
157         case DIR_D2A:
158                 if (mblog.cnt_da < 0xffffffff)
159                         mblog.cnt_da++;
160                 break;
161         }
162         if (++mblog.wp == MBLOG_DEPTH)
163                 mblog.wp = 0;
164         spin_unlock(&mblog.lock);
165 }
166
167 /*
168  * sysfs file
169  */
170 static ssize_t mblog_show(struct device *dev, struct device_attribute *attr,
171                           char *buf)
172 {
173         int len = 0;
174         int wp;
175         int i;
176
177         spin_lock(&mblog.lock);
178
179         wp = mblog.wp;
180         len += sprintf(buf + len,
181                        "log count:%ld / ARM->DSP:%ld, DSP->ARM:%ld\n",
182                        mblog.cnt, mblog.cnt_ad, mblog.cnt_da);
183         if (mblog.cnt == 0)
184                 goto done;
185
186         len += sprintf(buf + len, "          ARM -> DSP   ARM <- DSP\n");
187         len += sprintf(buf + len, "jiffies  q cmd  data q cmd  data\n");
188         i = (mblog.cnt >= MBLOG_DEPTH) ? wp : 0;
189         do {
190                 struct mblogent *ent = &mblog.ent[i];
191                 union {
192                         struct mbcmd sw;
193                         struct mbcmd_hw hw;
194                 } mb = {
195                         .hw.cmd  = ent->cmd,
196                         .hw.data = ent->data
197                 };
198                 char *subname;
199                 const struct cmdinfo *ci = cmdinfo[mb.sw.cmd_h];
200
201                 len += sprintf(buf + len,
202                                (ent->dir == DIR_A2D) ?
203                                 "%08lx %d %04x %04x             ":
204                                 "%08lx             %d %04x %04x ",
205                                ent->jiffies, mb.sw.seq, ent->cmd, ent->data);
206                 switch (ci->cmd_l_type) {
207                 case CMD_L_TYPE_SUBCMD:
208                         if ((subname = subcmd_name(&mb.sw)) == NULL)
209                                 subname = "Unknown";
210                         len += sprintf(buf + len, "%s:%s\n",
211                                        ci->name, subname);
212                         break;
213                 case CMD_L_TYPE_TID:
214                         len += sprintf(buf + len, "%s:task %d\n",
215                                        ci->name, mb.sw.cmd_l);
216                         break;
217                 case CMD_L_TYPE_NULL:
218                         len += sprintf(buf + len, "%s\n", ci->name);
219                         break;
220                 }
221
222                 if (++i == MBLOG_DEPTH)
223                         i = 0;
224         } while (i != wp);
225
226 done:
227         spin_unlock(&mblog.lock);
228
229         return len;
230 }
231
232 static struct device_attribute dev_attr_mblog = __ATTR_RO(mblog);
233
234 #ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
235 void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir dir)
236 {
237         const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
238         char *dir_str;
239         char *subname;
240
241         dir_str = (dir == DIR_A2D) ? "sending" : "receiving";
242         switch (ci->cmd_l_type) {
243         case CMD_L_TYPE_SUBCMD:
244                 if ((subname = subcmd_name(mb)) == NULL)
245                         subname = "Unknown";
246                 printk(KERN_DEBUG
247                        "mbx: %s seq=%d, cmd=%02x:%02x(%s:%s), data=%04x\n",
248                        dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
249                        ci->name, subname, mb->data);
250                 break;
251         case CMD_L_TYPE_TID:
252                 printk(KERN_DEBUG
253                        "mbx: %s seq=%d, cmd=%02x:%02x(%s:task %d), data=%04x\n",
254                        dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
255                        ci->name, mb->cmd_l, mb->data);
256                 break;
257         case CMD_L_TYPE_NULL:
258                 printk(KERN_DEBUG
259                        "mbx: %s seq=%d, cmd=%02x:%02x(%s), data=%04x\n",
260                        dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
261                        ci->name, mb->data);
262                 break;
263         }
264 }
265 #endif /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
266
267 void __init mblog_init(void)
268 {
269         spin_lock_init(&mblog.lock);
270         device_create_file(&dsp_device.dev, &dev_attr_mblog);
271 }
272
273 void mblog_exit(void)
274 {
275         device_remove_file(&dsp_device.dev, &dev_attr_mblog);
276 }