]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/dsp/error.c
dd7d7c4594bcbabdcf75e59c0191e706e2cdc6cb
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / dsp / error.c
1 /*
2  * linux/arch/arm/mach-omap/dsp/error.c
3  *
4  * OMAP DSP error detection I/F device driver
5  *
6  * Copyright (C) 2002-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/03/11:  DSP Gateway version 3.3
25  */
26
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/major.h>
30 #include <linux/fs.h>
31 #include <linux/poll.h>
32 #include <linux/sched.h>
33 #include <linux/interrupt.h>
34 #include <asm/uaccess.h>
35 #include <asm/io.h>
36 #include <asm/ioctls.h>
37 #include <asm/arch/dsp.h>
38 #include "dsp.h"
39
40 static DECLARE_WAIT_QUEUE_HEAD(err_wait_q);
41 static unsigned long errcode;
42 static int errcnt;
43 static unsigned short wdtval;   /* FIXME: read through ioctl */
44 static unsigned long 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 *buf, size_t count,
50                             loff_t *ppos)
51 {
52         unsigned long flags;
53         int status;
54
55         if (count < 4)
56                 return 0;
57
58         if (errcnt == 0) {
59                 long current_state;
60                 DECLARE_WAITQUEUE(wait, current);
61
62                 add_wait_queue(&err_wait_q, &wait);
63                 current_state = current->state;
64                 set_current_state(TASK_INTERRUPTIBLE);
65                 if (errcnt == 0)        /* last check */
66                         schedule();
67                 set_current_state(current_state);
68                 remove_wait_queue(&err_wait_q, &wait);
69                 if (signal_pending(current))
70                         return -EINTR;
71         }
72
73         local_irq_save(flags);
74         status = copy_to_user(buf, &errcode, 4);
75         if (status) {
76                 local_irq_restore(flags);
77                 return -EFAULT;
78         }
79         errcnt = 0;
80         local_irq_restore(flags);
81
82         return 4;
83 }
84
85 static unsigned int dsp_err_poll(struct file *file, poll_table *wait)
86 {
87         unsigned int mask = 0;
88
89         poll_wait(file, &err_wait_q, wait);
90         if (errcnt != 0)
91                 mask |= POLLIN | POLLRDNORM;
92
93         return mask;
94 }
95
96 struct file_operations dsp_err_fops = {
97         .owner = THIS_MODULE,
98         .poll  = dsp_err_poll,
99         .read  = dsp_err_read,
100 };
101
102 /*
103  * DSP MMU
104  */
105 void dsp_err_mmu_set(unsigned long adr)
106 {
107         disable_irq(INT_DSP_MMU);
108         errcode |= OMAP_DSP_ERRDT_MMU;
109         errcnt++;
110         mmu_fadr = adr;
111         wake_up_interruptible(&err_wait_q);
112 }
113
114 void dsp_err_mmu_clear(void)
115 {
116         errcode &= ~OMAP_DSP_ERRDT_MMU;
117         enable_irq(INT_DSP_MMU);
118 }
119
120 int dsp_err_mmu_isset(void)
121 {
122         return (errcode & OMAP_DSP_ERRDT_MMU) ? 1 : 0;
123 }
124
125 /*
126  * WDT
127  */
128 void dsp_err_wdt_clear(void)
129 {
130         errcode &= ~OMAP_DSP_ERRDT_WDT;
131 }
132
133 int dsp_err_wdt_isset(void)
134 {
135         return (errcode & OMAP_DSP_ERRDT_WDT) ? 1 : 0;
136 }
137
138 /*
139  * functions called from mailbox1 interrupt routine
140  */
141 static void mbx1_err_wdt(unsigned short data)
142 {
143         errcode |= OMAP_DSP_ERRDT_WDT;
144         errcnt++;
145         wdtval = data;
146         wake_up_interruptible(&err_wait_q);
147 }
148
149 #ifdef OLD_BINARY_SUPPORT
150 /* v3.3 obsolete */
151 void mbx1_wdt(struct mbcmd *mb)
152 {
153         mbx1_err_wdt(mb->data);
154 }
155 #endif
156
157 extern void mbx1_err_ipbfull(void);
158 extern void mbx1_err_fatal(unsigned char tid);
159
160 void mbx1_err(struct mbcmd *mb)
161 {
162         unsigned char eid = mb->cmd_l;
163         char *eidnm = subcmd_name(mb);
164         unsigned char tid;
165
166         if (eidnm) {
167                 printk(KERN_WARNING
168                        "mbx: ERR from DSP (%s): 0x%04x\n", eidnm, mb->data);
169         } else {
170                 printk(KERN_WARNING
171                        "mbx: ERR from DSP (unknown EID=%02x): %04x\n",
172                        eid, mb->data);
173         }
174
175         switch (eid) {
176         case OMAP_DSP_EID_IPBFULL:
177                 mbx1_err_ipbfull();
178                 break;
179
180         case OMAP_DSP_EID_FATAL:
181                 tid = mb->data & 0x00ff;
182                 mbx1_err_fatal(tid);
183                 break;
184
185         case OMAP_DSP_EID_WDT:
186                 mbx1_err_wdt(mb->data);
187                 break;
188         }
189 }
190
191 /*
192  *
193  */
194 void dsp_err_start(void)
195 {
196         errcnt = 0;
197         if (dsp_err_wdt_isset())
198                 dsp_err_wdt_clear();
199         if (dsp_err_mmu_isset())
200                 dsp_err_mmu_clear();
201 }
202
203 void dsp_err_stop(void)
204 {
205         wake_up_interruptible(&err_wait_q);
206 }