From: Ernesto Ramos <ernesto@xxxxxx> Cleaned up by Felipe Contreras. Signed-off-by: Felipe Contreras <felipe.contreras@xxxxxxxxx> --- drivers/dsp/bridge/wmd/ue_deh.c | 55 ++++++++++++++++++++++++++++++++++++-- 1 files changed, 52 insertions(+), 3 deletions(-) diff --git a/drivers/dsp/bridge/wmd/ue_deh.c b/drivers/dsp/bridge/wmd/ue_deh.c index 451ee3c..3678e1d 100644 --- a/drivers/dsp/bridge/wmd/ue_deh.c +++ b/drivers/dsp/bridge/wmd/ue_deh.c @@ -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); -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html