4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * Implements upper edge DSP exception handling (DEH) functions.
8 * Copyright (C) 2005-2006 Texas Instruments, Inc.
9 * Copyright (C) 2010 Felipe Contreras
11 * This package is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 #include <linux/kernel.h>
21 #include <linux/interrupt.h>
22 #include <plat/dmtimer.h>
24 #include <dspbridge/dbdefs.h>
25 #include <dspbridge/dspdeh.h>
26 #include <dspbridge/dev.h>
30 #include <dspbridge/io_sm.h>
31 #include <dspbridge/drv.h>
32 #include <dspbridge/wdt.h>
34 int bridge_deh_create(struct deh_mgr **ret_deh,
35 struct dev_object *hdev_obj)
39 struct bridge_dev_context *hbridge_context = NULL;
41 /* Message manager will be created when a file is loaded, since
42 * size of message buffer in shared memory is configurable in
44 /* Get Bridge context info. */
45 dev_get_bridge_context(hdev_obj, &hbridge_context);
46 /* Allocate IO manager object: */
47 deh = kzalloc(sizeof(*deh), GFP_KERNEL);
53 /* Create an NTFY object to manage notifications */
54 deh->ntfy_obj = kmalloc(sizeof(struct ntfy_object), GFP_KERNEL);
59 ntfy_init(deh->ntfy_obj);
61 /* Fill in context structure */
62 deh->hbridge_context = hbridge_context;
68 bridge_deh_destroy(deh);
73 int bridge_deh_destroy(struct deh_mgr *deh)
78 /* If notification object exists, delete it */
80 ntfy_delete(deh->ntfy_obj);
84 /* Deallocate the DEH manager object */
90 int bridge_deh_register_notify(struct deh_mgr *deh, u32 event_mask,
92 struct dsp_notification *hnotification)
98 return ntfy_register(deh->ntfy_obj, hnotification,
99 event_mask, notify_type);
101 return ntfy_unregister(deh->ntfy_obj, hnotification);
104 static inline const char *event_to_string(int event)
107 case DSP_SYSERROR: return "DSP_SYSERROR"; break;
108 case DSP_MMUFAULT: return "DSP_MMUFAULT"; break;
109 case DSP_PWRERROR: return "DSP_PWRERROR"; break;
110 case DSP_WDTOVERFLOW: return "DSP_WDTOVERFLOW"; break;
111 default: return "unkown event"; break;
115 void bridge_deh_notify(struct deh_mgr *deh, int event, int info)
117 struct bridge_dev_context *dev_context;
118 const char *str = event_to_string(event);
123 dev_dbg(bridge, "%s: device exception", __func__);
124 dev_context = deh->hbridge_context;
128 dev_err(bridge, "%s: %s, info=0x%x", __func__,
130 #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
131 dump_dl_modules(dev_context);
132 dump_dsp_stack(dev_context);
136 dev_err(bridge, "%s: %s, addr=0x%x", __func__, str, info);
139 dev_err(bridge, "%s: %s", __func__, str);
143 /* Filter subsequent notifications when an error occurs */
144 if (dev_context->dw_brd_state != BRD_ERROR) {
145 ntfy_notify(deh->ntfy_obj, event);
146 #ifdef CONFIG_TIDSPBRIDGE_RECOVERY
147 bridge_recover_schedule();
151 /* Set the Board state as ERROR */
152 dev_context->dw_brd_state = BRD_ERROR;
153 /* Disable all the clocks that were enabled by DSP */
154 dsp_clock_disable_all(dev_context->dsp_per_clks);
156 * Avoid the subsequent WDT if it happens once,
157 * also if fatal error occurs.
159 dsp_wdt_enable(false);