@@ -53,8 +53,17 @@
#include "_tiomap_pwr.h"
#include <dspbridge/io_sm.h>
+#include <plat/dmtimer.h>
+
#define ALIGN_DOWN(x, a) ((x)&(~((a)-1)))
+/* GP Timer number to trigger interrupt for MMU-fault ISR on DSP */
+#define GPTIMER_FOR_DSP_MMU_FAULT 8
+/* Bit mask to enable overflow interrupt */
+#define GPTIMER_IRQ_OVERFLOW 2
+/* Max time to check for GP Timer IRQ */
+#define GPTIMER_IRQ_WAIT_MAX_CNT 1000
+
static struct hw_mmu_map_attrs_t map_attrs = { HW_LITTLE_ENDIAN,
HW_ELEM_SIZE16BIT,
HW_MMU_CPUES
@@ -62,6 +71,8 @@ static struct hw_mmu_map_attrs_t map_attrs = { HW_LITTLE_ENDIAN,
static void *dummy_va_addr;
+static struct omap_dm_timer *timer;
+
dsp_status bridge_deh_create(struct deh_mgr **ret_deh_mgr,
struct dev_object *hdev_obj)
{
@@ -128,6 +139,15 @@ err:
bridge_deh_destroy(deh_mgr);
deh_mgr = NULL;
}
+ else {
+ timer = omap_dm_timer_request_specific(
+ GPTIMER_FOR_DSP_MMU_FAULT);
+ if (!timer) {
+ pr_err("%s: GPTimer not available\n", __func__);
+ return -ENODEV;
+ }
+ omap_dm_timer_disable(timer);
+ }
leave:
*ret_deh_mgr = deh_mgr;
@@ -156,6 +176,10 @@ dsp_status bridge_deh_destroy(struct deh_mgr *deh_mgr)
/* Deallocate the DEH manager object */
MEM_FREE_OBJECT(deh_mgr);
+ /* The GPTimer is no longer needed */
+ omap_dm_timer_free(timer);
+ timer = NULL;
+
return DSP_SOK;
}
@@ -177,6 +201,31 @@ dsp_status bridge_deh_register_notify(struct deh_mgr *deh_mgr, u32 event_mask,
return status;
}
+static void wait_for_timer()
+{
+ int c;
+
+ omap_dm_timer_enable(timer);
+ /* Enable overflow interrupt */
+ omap_dm_timer_set_int_enable(timer,
+ GPTIMER_IRQ_OVERFLOW);
+ /*
+ * Set counter value to overflow counter after
+ * one tick and start timer.
+ */
+ omap_dm_timer_set_load_start(timer, 0, 0xfffffffe);
+
+ /* Wait 80us for timer to overflow */
+ udelay(80);
+
+ /* Check interrupt status and wait for interrupt */
+ for (c = 0; c < GPTIMER_IRQ_WAIT_MAX_CNT; c++)
+ if ((omap_dm_timer_read_status(timer) & GPTIMER_IRQ_OVERFLOW))
+ return;
+
+ pr_err("%s: GPTimer interrupt failed\n", __func__);
+}
+
void bridge_deh_notify(struct deh_mgr *deh_mgr, u32 ulEventMask, u32 dwErrInfo)
{
struct wmd_dev_context *dev_context;
@@ -241,9 +290,9 @@ void bridge_deh_notify(struct deh_mgr *deh_mgr, u32 ulEventMask, u32 dwErrInfo)
HW_PAGE_SIZE4KB, 1,
&map_attrs, HW_SET, HW_SET);
}
- /* send an interrupt to DSP */
- omap_mbox_msg_send(dev_context->mbox,
- MBX_DEH_CLASS | MBX_DEH_EMMU);
+
+ wait_for_timer();
+
/* Clear MMU interrupt */
hw_mmu_event_ack(resources.dw_dmmu_base,
HW_MMU_TRANSLATION_FAULT);