]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/dsp/dspgateway/error.c
66d9c8aa51fc7acf80d8a7e8a403da0e87dd3e86
[linux-2.6-omap-h63xx.git] / drivers / dsp / dspgateway / error.c
1 /*
2  * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
3  *
4  * Copyright (C) 2002-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/module.h>
25 #include <linux/fs.h>
26 #include <linux/poll.h>
27 #include <linux/sched.h>
28 #include <linux/interrupt.h>
29 #include <mach/mailbox.h>
30 #include <asm/uaccess.h>
31 #include "dsp_mbcmd.h"
32 #include "dsp.h"
33
34 /*
35  * value seen through read()
36  */
37 #define DSP_ERR_WDT     0x00000001
38 #define DSP_ERR_MMU     0x00000002
39 static unsigned long errval;
40
41 static DECLARE_WAIT_QUEUE_HEAD(err_wait_q);
42 static int errcnt;
43 static u16 wdtval;      /* FIXME: read through ioctl */
44 static u32 mmu_fadr;    /* FIXME: read through ioctl */
45
46 /*
47  * DSP error detection device file operations
48  */
49 static ssize_t dsp_err_read(struct file *file, char __user *buf, size_t count,
50                             loff_t *ppos)
51 {
52         unsigned long flags;
53         int status;
54         DEFINE_WAIT(wait);
55
56         if (count < 4)
57                 return 0;
58
59         prepare_to_wait(&err_wait_q, &wait, TASK_INTERRUPTIBLE);
60         if (errcnt == 0)
61                 schedule();
62         finish_wait(&err_wait_q, &wait);
63         if (signal_pending(current))
64                 return -EINTR;
65
66         local_irq_save(flags);
67         status = copy_to_user(buf, &errval, 4);
68         if (status) {
69                 local_irq_restore(flags);
70                 return -EFAULT;
71         }
72         errcnt = 0;
73         local_irq_restore(flags);
74
75         return 4;
76 }
77
78 static unsigned int dsp_err_poll(struct file *file, poll_table *wait)
79 {
80         unsigned int mask = 0;
81
82         poll_wait(file, &err_wait_q, wait);
83         if (errcnt != 0)
84                 mask |= POLLIN | POLLRDNORM;
85
86         return mask;
87 }
88
89 struct file_operations dsp_err_fops = {
90         .owner = THIS_MODULE,
91         .poll  = dsp_err_poll,
92         .read  = dsp_err_read,
93 };
94
95 /*
96  * set / clear functions
97  */
98
99 /* DSP MMU */
100 static void dsp_err_mmu_set(unsigned long arg)
101 {
102         disable_irq(omap_dsp->mmu->irq);
103         mmu_fadr = (u32)arg;
104 }
105
106 static void dsp_err_mmu_clr(void)
107 {
108         enable_irq(omap_dsp->mmu->irq);
109 }
110
111 /* WDT */
112 static void dsp_err_wdt_set(unsigned long arg)
113 {
114         wdtval = (u16)arg;
115 }
116
117 /*
118  * error code handler
119  */
120 static struct {
121         unsigned long val;
122         void (*set)(unsigned long arg);
123         void (*clr)(void);
124 } dsp_err_desc[ERRCODE_MAX] = {
125         [ERRCODE_MMU] = { DSP_ERR_MMU, dsp_err_mmu_set, dsp_err_mmu_clr },
126         [ERRCODE_WDT] = { DSP_ERR_WDT, dsp_err_wdt_set, NULL },
127 };
128
129 void dsp_err_set(enum errcode_e code, unsigned long arg)
130 {
131         if (dsp_err_desc[code].set != NULL)
132                 dsp_err_desc[code].set(arg);
133
134         errval |= dsp_err_desc[code].val;
135         errcnt++;
136         wake_up_interruptible(&err_wait_q);
137 }
138
139 void dsp_err_clear(enum errcode_e code)
140 {
141         errval &= ~dsp_err_desc[code].val;
142
143         if (dsp_err_desc[code].clr != NULL)
144                 dsp_err_desc[code].clr();
145 }
146
147 int dsp_err_isset(enum errcode_e code)
148 {
149         return (errval & dsp_err_desc[code].val) ? 1 : 0;
150 }
151
152 void dsp_err_notify(void)
153 {
154         /* new error code should be assigned */
155         dsp_err_set(DSP_ERR_WDT, 0);
156 }
157
158 /*
159  * functions called from mailbox interrupt routine
160  */
161 static void mbox_err_wdt(u16 data)
162 {
163         dsp_err_set(DSP_ERR_WDT, (unsigned long)data);
164 }
165
166 #ifdef OLD_BINARY_SUPPORT
167 /* v3.3 obsolete */
168 void mbox_wdt(struct mbcmd *mb)
169 {
170         mbox_err_wdt(mb->data);
171 }
172 #endif
173
174 extern void mbox_err_ipbfull(void);
175 extern void mbox_err_fatal(u8 tid);
176
177 void mbox_err(struct mbcmd *mb)
178 {
179         u8 eid = mb->cmd_l;
180         char *eidnm = subcmd_name(mb);
181         u8 tid;
182
183         if (eidnm) {
184                 printk(KERN_WARNING
185                        "mbox: ERR from DSP (%s): 0x%04x\n", eidnm, mb->data);
186         } else {
187                 printk(KERN_WARNING
188                        "mbox: ERR from DSP (unknown EID=%02x): %04x\n",
189                        eid, mb->data);
190         }
191
192         switch (eid) {
193         case EID_IPBFULL:
194                 mbox_err_ipbfull();
195                 break;
196
197         case EID_FATAL:
198                 tid = mb->data & 0x00ff;
199                 mbox_err_fatal(tid);
200                 break;
201
202         case EID_WDT:
203                 mbox_err_wdt(mb->data);
204                 break;
205         }
206 }
207
208 /*
209  *
210  */
211 void dsp_err_start(void)
212 {
213         enum errcode_e i;
214
215         for (i = 0; i < ERRCODE_MAX; i++) {
216                 if (dsp_err_isset(i))
217                         dsp_err_clear(i);
218         }
219         omap_dsp->mbox->err_notify = dsp_err_notify;
220         errcnt = 0;
221 }
222
223 void dsp_err_stop(void)
224 {
225         wake_up_interruptible(&err_wait_q);
226         omap_dsp->mbox->err_notify = NULL;
227 }