]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/tidspbridge/core/ue_deh.c
staging: ti dspbridge: remove unused code
[net-next-2.6.git] / drivers / staging / tidspbridge / core / ue_deh.c
1 /*
2  * ue_deh.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * Implements upper edge DSP exception handling (DEH) functions.
7  *
8  * Copyright (C) 2005-2006 Texas Instruments, Inc.
9  *
10  * This package is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  */
18
19 /*  ----------------------------------- Host OS */
20 #include <dspbridge/host_os.h>
21
22 /*  ----------------------------------- DSP/BIOS Bridge */
23 #include <dspbridge/std.h>
24 #include <dspbridge/dbdefs.h>
25
26 /*  ----------------------------------- Trace & Debug */
27 #include <dspbridge/dbc.h>
28
29 /*  ----------------------------------- OS Adaptation Layer */
30 #include <dspbridge/cfg.h>
31 #include <dspbridge/clk.h>
32 #include <dspbridge/ntfy.h>
33 #include <dspbridge/drv.h>
34
35 /*  ----------------------------------- Link Driver */
36 #include <dspbridge/dspdeh.h>
37
38 /*  ----------------------------------- Platform Manager */
39 #include <dspbridge/dev.h>
40 #include <dspbridge/dspapi.h>
41 #include <dspbridge/wdt.h>
42
43 /* ------------------------------------ Hardware Abstraction Layer */
44 #include <hw_defs.h>
45 #include <hw_mmu.h>
46
47 /*  ----------------------------------- This */
48 #include "mmu_fault.h"
49 #include "_tiomap.h"
50 #include "_deh.h"
51 #include "_tiomap_pwr.h"
52 #include <dspbridge/io_sm.h>
53
54
55 int bridge_deh_create(struct deh_mgr **ret_deh_mgr,
56                 struct dev_object *hdev_obj)
57 {
58         int status = 0;
59         struct deh_mgr *deh_mgr;
60         struct bridge_dev_context *hbridge_context = NULL;
61
62         /*  Message manager will be created when a file is loaded, since
63          *  size of message buffer in shared memory is configurable in
64          *  the base image. */
65         /* Get Bridge context info. */
66         dev_get_bridge_context(hdev_obj, &hbridge_context);
67         /* Allocate IO manager object: */
68         deh_mgr = kzalloc(sizeof(struct deh_mgr), GFP_KERNEL);
69         if (!deh_mgr) {
70                 status = -ENOMEM;
71                 goto err;
72         }
73
74         /* Create an NTFY object to manage notifications */
75         deh_mgr->ntfy_obj = kmalloc(sizeof(struct ntfy_object), GFP_KERNEL);
76         if (!deh_mgr->ntfy_obj) {
77                 status = -ENOMEM;
78                 goto err;
79         }
80         ntfy_init(deh_mgr->ntfy_obj);
81
82         /* Create a MMUfault DPC */
83         tasklet_init(&deh_mgr->dpc_tasklet, mmu_fault_dpc, (u32) deh_mgr);
84
85         /* Fill in context structure */
86         deh_mgr->hbridge_context = hbridge_context;
87         deh_mgr->err_info.dw_err_mask = 0L;
88         deh_mgr->err_info.dw_val1 = 0L;
89         deh_mgr->err_info.dw_val2 = 0L;
90         deh_mgr->err_info.dw_val3 = 0L;
91
92         /* Install ISR function for DSP MMU fault */
93         status = request_irq(INT_DSP_MMU_IRQ, mmu_fault_isr, 0,
94                         "DspBridge\tiommu fault", deh_mgr);
95         if (status < 0)
96                 goto err;
97
98         *ret_deh_mgr = deh_mgr;
99         return 0;
100
101 err:
102         bridge_deh_destroy(deh_mgr);
103         *ret_deh_mgr = NULL;
104         return status;
105 }
106
107 int bridge_deh_destroy(struct deh_mgr *deh_mgr)
108 {
109         if (!deh_mgr)
110                 return -EFAULT;
111
112         /* If notification object exists, delete it */
113         if (deh_mgr->ntfy_obj) {
114                 ntfy_delete(deh_mgr->ntfy_obj);
115                 kfree(deh_mgr->ntfy_obj);
116         }
117         /* Disable DSP MMU fault */
118         free_irq(INT_DSP_MMU_IRQ, deh_mgr);
119
120         /* Free DPC object */
121         tasklet_kill(&deh_mgr->dpc_tasklet);
122
123         /* Deallocate the DEH manager object */
124         kfree(deh_mgr);
125
126         return 0;
127 }
128
129 int bridge_deh_register_notify(struct deh_mgr *deh_mgr, u32 event_mask,
130                 u32 notify_type,
131                 struct dsp_notification *hnotification)
132 {
133         if (!deh_mgr)
134                 return -EFAULT;
135
136         if (event_mask)
137                 return ntfy_register(deh_mgr->ntfy_obj, hnotification,
138                                 event_mask, notify_type);
139         else
140                 return ntfy_unregister(deh_mgr->ntfy_obj, hnotification);
141 }
142
143 void bridge_deh_notify(struct deh_mgr *deh_mgr, u32 ulEventMask, u32 dwErrInfo)
144 {
145         struct bridge_dev_context *dev_context;
146         struct cfg_hostres *resources;
147         struct hw_mmu_map_attrs_t map_attrs = {
148                 .endianism = HW_LITTLE_ENDIAN,
149                 .element_size = HW_ELEM_SIZE16BIT,
150                 .mixed_size = HW_MMU_CPUES,
151         };
152         void *dummy_va_addr;
153
154         if (!deh_mgr)
155                 return;
156
157         dev_info(bridge, "%s: device exception\n", __func__);
158         dev_context = deh_mgr->hbridge_context;
159         resources = dev_context->resources;
160
161         switch (ulEventMask) {
162         case DSP_SYSERROR:
163                 /* reset err_info structure before use */
164                 deh_mgr->err_info.dw_err_mask = DSP_SYSERROR;
165                 deh_mgr->err_info.dw_val1 = 0L;
166                 deh_mgr->err_info.dw_val2 = 0L;
167                 deh_mgr->err_info.dw_val3 = 0L;
168                 deh_mgr->err_info.dw_val1 = dwErrInfo;
169                 dev_err(bridge, "%s: %s, err_info = 0x%x\n",
170                                 __func__, "DSP_SYSERROR", dwErrInfo);
171                 dump_dl_modules(dev_context);
172                 dump_dsp_stack(dev_context);
173                 break;
174         case DSP_MMUFAULT:
175                 /* MMU fault routine should have set err info structure. */
176                 deh_mgr->err_info.dw_err_mask = DSP_MMUFAULT;
177                 dev_err(bridge, "%s: %s, err_info = 0x%x\n",
178                                 __func__, "DSP_MMUFAULT", dwErrInfo);
179                 dev_info(bridge, "%s: %s, high=0x%x, low=0x%x, "
180                         "fault=0x%x\n", __func__, "DSP_MMUFAULT",
181                         (unsigned int) deh_mgr->err_info.dw_val1,
182                         (unsigned int) deh_mgr->err_info.dw_val2,
183                         (unsigned int) fault_addr);
184                 dummy_va_addr = (void*)__get_free_page(GFP_ATOMIC);
185
186                 print_dsp_trace_buffer(dev_context);
187                 dump_dl_modules(dev_context);
188
189                 hw_mmu_tlb_add(resources->dw_dmmu_base,
190                                 virt_to_phys(dummy_va_addr), fault_addr,
191                                 HW_PAGE_SIZE4KB, 1,
192                                 &map_attrs, HW_SET, HW_SET);
193
194                 dsp_clk_enable(DSP_CLK_GPT8);
195
196                 dsp_gpt_wait_overflow(DSP_CLK_GPT8, 0xfffffffe);
197
198                 /* Clear MMU interrupt */
199                 hw_mmu_event_ack(resources->dw_dmmu_base,
200                                 HW_MMU_TRANSLATION_FAULT);
201                 dump_dsp_stack(dev_context);
202                 dsp_clk_disable(DSP_CLK_GPT8);
203
204                 hw_mmu_disable(resources->dw_dmmu_base);
205                 free_page((unsigned long)dummy_va_addr);
206                 break;
207 #ifdef CONFIG_BRIDGE_NTFY_PWRERR
208         case DSP_PWRERROR:
209                 /* reset err_info structure before use */
210                 deh_mgr->err_info.dw_err_mask = DSP_PWRERROR;
211                 deh_mgr->err_info.dw_val1 = 0L;
212                 deh_mgr->err_info.dw_val2 = 0L;
213                 deh_mgr->err_info.dw_val3 = 0L;
214                 deh_mgr->err_info.dw_val1 = dwErrInfo;
215                 dev_err(bridge, "%s: %s, err_info = 0x%x\n",
216                                 __func__, "DSP_PWRERROR", dwErrInfo);
217                 break;
218 #endif /* CONFIG_BRIDGE_NTFY_PWRERR */
219         case DSP_WDTOVERFLOW:
220                 deh_mgr->err_info.dw_err_mask = DSP_WDTOVERFLOW;
221                 deh_mgr->err_info.dw_val1 = 0L;
222                 deh_mgr->err_info.dw_val2 = 0L;
223                 deh_mgr->err_info.dw_val3 = 0L;
224                 dev_err(bridge, "%s: DSP_WDTOVERFLOW\n", __func__);
225                 break;
226         default:
227                 dev_dbg(bridge, "%s: Unknown Error, err_info = 0x%x\n",
228                                 __func__, dwErrInfo);
229                 break;
230         }
231
232         /* Filter subsequent notifications when an error occurs */
233         if (dev_context->dw_brd_state != BRD_ERROR) {
234                 ntfy_notify(deh_mgr->ntfy_obj, ulEventMask);
235 #ifdef CONFIG_BRIDGE_RECOVERY
236                 bridge_recover_schedule();
237 #endif
238         }
239
240         /* Set the Board state as ERROR */
241         dev_context->dw_brd_state = BRD_ERROR;
242         /* Disable all the clocks that were enabled by DSP */
243         dsp_clock_disable_all(dev_context->dsp_per_clks);
244         /*
245          * Avoid the subsequent WDT if it happens once,
246          * also if fatal error occurs.
247          */
248         dsp_wdt_enable(false);
249 }
250
251 int bridge_deh_get_info(struct deh_mgr *deh_mgr,
252                 struct dsp_errorinfo *pErrInfo)
253 {
254         if (!deh_mgr)
255                 return -EFAULT;
256
257         /* Copy DEH error info structure to PROC error info structure. */
258         pErrInfo->dw_err_mask = deh_mgr->err_info.dw_err_mask;
259         pErrInfo->dw_val1 = deh_mgr->err_info.dw_val1;
260         pErrInfo->dw_val2 = deh_mgr->err_info.dw_val2;
261         pErrInfo->dw_val3 = deh_mgr->err_info.dw_val3;
262
263         return 0;
264 }