Hi All,
I forgot to mention that you need DSP side changes too, at lest you need 4.57-P2 DSP binaries. They will be updated in userspace-dspbridge project in d.o.z Regards, Fernando. >-----Original Message----- >From: linux-omap-ow...@vger.kernel.org [mailto:linux-omap- >ow...@vger.kernel.org] On Behalf Of Guzman Lugo, Fernando >Sent: Tuesday, March 30, 2010 9:44 PM >To: linux-omap@vger.kernel.org >Cc: Hiroshi DOYU; Ameya Palande; felipe.contre...@nokia.com >Subject: DSPBRIDGE: Implement WDT3 to notify DSP hangs > >From 7349444302a782997d6eba64d46908c0915c12a1 Mon Sep 17 00:00:00 2001 >From: Fernando Guzman Lugo <x0095...@ti.com> >Date: Tue, 30 Mar 2010 21:52:25 -0600 >Subject: [PATCH] DSPBRIDGE: Implement WDT3 to notify DSP hangs > >This patch implements wdt3 feature to notify wdt3 overflow. >This new feature can be chosen by doing make menuconfig, >default is disabled. > >WDT3 is upcount Timer incrementing every functional clock tick >till it reaches programmed timeout value. On reaching timeout >value, if INTerrupt bit for WDT3 is enabled, then an interrupt >is generated to MPU. > >After receiving this Interrupt, any client can register within >bridge driver to be notified of this event and prepare for >DSP recovery. > >Signed-off-by: Fernando Guzman Lugo <x0095...@ti.com> >Signed-off-by: Armando Uribe <x0095...@ti.com> >Signed-off-by: Somashekar Chandrappa <somasheka...@ti.com> >--- > arch/arm/plat-omap/include/dspbridge/_chnl_sm.h | 7 + > arch/arm/plat-omap/include/dspbridge/cfgdefs.h | 1 - > arch/arm/plat-omap/include/dspbridge/dbdefs.h | 3 + > arch/arm/plat-omap/include/dspbridge/wdt.h | 79 ++++++++++++ > arch/arm/plat-omap/include/plat/omap34xx.h | 3 + > drivers/dsp/bridge/Kconfig | 17 +++ > drivers/dsp/bridge/Makefile | 2 +- > drivers/dsp/bridge/rmgr/drv.c | 8 -- > drivers/dsp/bridge/rmgr/proc.c | 8 +- > drivers/dsp/bridge/wmd/io_sm.c | 4 + > drivers/dsp/bridge/wmd/tiomap3430.c | 7 + > drivers/dsp/bridge/wmd/tiomap3430_pwr.c | 7 + > drivers/dsp/bridge/wmd/tiomap_io.c | 2 + > drivers/dsp/bridge/wmd/ue_deh.c | 13 ++ > drivers/dsp/bridge/wmd/wdt.c | 148 >+++++++++++++++++++++++ > 15 files changed, 296 insertions(+), 13 deletions(-) > create mode 100644 arch/arm/plat-omap/include/dspbridge/wdt.h > create mode 100644 drivers/dsp/bridge/wmd/wdt.c > >diff --git a/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h >b/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h >index f394ba6..f8bdc93 100644 >--- a/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h >+++ b/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h >@@ -99,7 +99,14 @@ struct shm { > struct opp_rqst_struct opp_request; > /* load monitor information structure */ > struct load_mon_struct load_mon_info; >+#ifdef CONFIG_BRIDGE_WDT3 >+ /* Flag for WDT enable/disable F/I clocks */ >+ u32 wdt_setclocks; >+ u32 wdt_overflow; /* WDT overflow time */ >+ char dummy[176]; /* padding to 256 byte boundary */ >+#else > char dummy[184]; /* padding to 256 byte boundary */ >+#endif > u32 shm_dbg_var[64]; /* shared memory debug variables */ > }; > >diff --git a/arch/arm/plat-omap/include/dspbridge/cfgdefs.h >b/arch/arm/plat-omap/include/dspbridge/cfgdefs.h >index bd24611..a71fc7b 100644 >--- a/arch/arm/plat-omap/include/dspbridge/cfgdefs.h >+++ b/arch/arm/plat-omap/include/dspbridge/cfgdefs.h >@@ -70,7 +70,6 @@ struct cfg_hostres { > void __iomem *dw_per_base; > u32 dw_per_pm_base; > u32 dw_core_pm_base; >- void __iomem *dw_wd_timer_dsp_base; > void __iomem *dw_dmmu_base; > void __iomem *dw_sys_ctrl_base; > }; >diff --git a/arch/arm/plat-omap/include/dspbridge/dbdefs.h b/arch/arm/plat- >omap/include/dspbridge/dbdefs.h >index 7fcc4aa..b5d3097 100644 >--- a/arch/arm/plat-omap/include/dspbridge/dbdefs.h >+++ b/arch/arm/plat-omap/include/dspbridge/dbdefs.h >@@ -53,6 +53,7 @@ > #define DSP_SYSERROR 0x00000020 > #define DSP_EXCEPTIONABORT 0x00000300 > #define DSP_PWRERROR 0x00000080 >+#define DSP_WDTOVERFLOW 0x00000040 > > /* IVA exception events (IVA MMU fault) */ > #define IVA_MMUFAULT 0x00000040 >@@ -124,6 +125,7 @@ typedef u32 dsp_status; /* API return code >type */ > DSP_STREAMIOCOMPLETION | \ > DSP_MMUFAULT | \ > DSP_SYSERROR | \ >+ DSP_WDTOVERFLOW | \ > DSP_PWRERROR)) && \ > !((x) & ~(DSP_PROCESSORSTATECHANGE | \ > DSP_PROCESSORATTACH | \ >@@ -134,6 +136,7 @@ typedef u32 dsp_status; /* API return code >type */ > DSP_STREAMIOCOMPLETION | \ > DSP_MMUFAULT | \ > DSP_SYSERROR | \ >+ DSP_WDTOVERFLOW | \ > DSP_PWRERROR)))) > > #define IS_VALID_NODE_EVENT(x) (((x) == 0) || \ >diff --git a/arch/arm/plat-omap/include/dspbridge/wdt.h b/arch/arm/plat- >omap/include/dspbridge/wdt.h >new file mode 100644 >index 0000000..4c00ba5 >--- /dev/null >+++ b/arch/arm/plat-omap/include/dspbridge/wdt.h >@@ -0,0 +1,79 @@ >+/* >+ * wdt.h >+ * >+ * DSP-BIOS Bridge driver support functions for TI OMAP processors. >+ * >+ * IO dispatcher for a shared memory channel driver. >+ * >+ * Copyright (C) 2010 Texas Instruments, Inc. >+ * >+ * This package is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License version 2 as >+ * published by the Free Software Foundation. >+ * >+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR >+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED >+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. >+ */ >+#ifndef __DSP_WDT3_H_ >+#define __DSP_WDT3_H_ >+ >+/* WDT defines */ >+#define OMAP3_WDT3_ISR_OFFSET 0x0018 >+ >+ >+/** >+ * struct dsp_wdt_setting - the basic dsp_wdt_setting structure >+ * @reg_base: pointer to the base of the wdt registers >+ * @sm_wdt: pointer to flags in shared memory >+ * @wdt3_tasklet tasklet to manage wdt event >+ * @fclk handle to wdt3 functional clock >+ * @iclk handle to wdt3 interface clock >+ * >+ * This struct is used in the function to manage wdt3. >+ */ >+ >+struct dsp_wdt_setting { >+ void __iomem *reg_base; >+ struct shm *sm_wdt; >+ struct tasklet_struct wdt3_tasklet; >+ struct clk *fclk; >+ struct clk *iclk; >+}; >+ >+/** >+ * dsp_wdt_init() - initialize wdt3 module. >+ * >+ * This function initilize to wdt3 module, so that >+ * other wdt3 function can be used. >+ */ >+int dsp_wdt_init(void); >+ >+/** >+ * dsp_wdt_exit() - initialize wdt3 module. >+ * >+ * This function frees all resources allocated for wdt3 module. >+ */ >+void dsp_wdt_exit(void); >+ >+/** >+ * dsp_wdt_enable() - enable/disable wdt3 >+ * @enable: bool value to enable/disable wdt3 >+ * >+ * This function enables or disables wdt3 base on @enable value. >+ * >+ */ >+void dsp_wdt_enable(bool enable); >+ >+/** >+ * dsp_wdt_sm_set() - store pointer to the share memory >+ * @data: pointer to dspbridge share memory >+ * >+ * This function is used to pass a valid pointer to share memory, >+ * so that the flags can be set in order DSP side can read them. >+ * >+ */ >+void dsp_wdt_sm_set(void *data); >+ >+#endif >+ >diff --git a/arch/arm/plat-omap/include/plat/omap34xx.h b/arch/arm/plat- >omap/include/plat/omap34xx.h >index 077f059..dded9cc 100644 >--- a/arch/arm/plat-omap/include/plat/omap34xx.h >+++ b/arch/arm/plat-omap/include/plat/omap34xx.h >@@ -82,5 +82,8 @@ > > #define OMAP34XX_MAILBOX_BASE (L4_34XX_BASE + 0x94000) > >+#define OMAP34XX_WDT3_BASE (L4_PER_34XX_BASE + 0x30000) >+ >+ > #endif /* __ASM_ARCH_OMAP34XX_H */ > >diff --git a/drivers/dsp/bridge/Kconfig b/drivers/dsp/bridge/Kconfig >index 23b2afc..fcd035c 100644 >--- a/drivers/dsp/bridge/Kconfig >+++ b/drivers/dsp/bridge/Kconfig >@@ -45,6 +45,23 @@ config BRIDGE_RECOVERY > In case of DSP fatal error, BRIDGE driver will try to > recover itself. > >+config BRIDGE_WDT3 >+ bool "Enable WDT3 interruptions" >+ depends on MPU_BRIDGE >+ default n >+ help >+ WTD3 is managed by DSP and once it is enabled, DSP side bridge is >in >+ charge of refreshing the timer before overflow, if the DSP hangs >MPU >+ will caught the interrupt and try to recover DSP. >+ >+config WDT_TIMEOUT >+ int "DSP watchdog timer timeout (in secs)" >+ depends on BRIDGE_WDT3 >+ default 5 >+ help >+ Watchdog timer timeout value, after that time if the watchdog >timer >+ counter is not reset the wdt overflow interrupt will be >triggered >+ > comment "Bridge Notifications" > depends on MPU_BRIDGE > >diff --git a/drivers/dsp/bridge/Makefile b/drivers/dsp/bridge/Makefile >index 2b4f92c..ce85ba6 100644 >--- a/drivers/dsp/bridge/Makefile >+++ b/drivers/dsp/bridge/Makefile >@@ -7,7 +7,7 @@ libservices = services/mem.o services/sync.o \ > services/services.o > libwmd = wmd/chnl_sm.o wmd/msg_sm.o wmd/io_sm.o wmd/tiomap3430.o \ > wmd/tiomap3430_pwr.o wmd/tiomap_io.o \ >- wmd/mmu_fault.o wmd/ue_deh.o >+ wmd/mmu_fault.o wmd/ue_deh.o wmd/wdt.o > libpmgr = pmgr/chnl.o pmgr/io.o pmgr/msg.o pmgr/cod.o pmgr/dev.o >pmgr/wcd.o \ > pmgr/dmm.o pmgr/cmm.o pmgr/dbll.o > librmgr = rmgr/dbdcd.o rmgr/disp.o rmgr/drv.o rmgr/mgr.o rmgr/node.o \ >diff --git a/drivers/dsp/bridge/rmgr/drv.c b/drivers/dsp/bridge/rmgr/drv.c >index 98f9b78..fe9ae06 100644 >--- a/drivers/dsp/bridge/rmgr/drv.c >+++ b/drivers/dsp/bridge/rmgr/drv.c >@@ -904,8 +904,6 @@ static dsp_status request_bridge_resources(u32 >dw_context, s32 bRequest) > iounmap((void *)host_res->dw_mem_base[3]); > if (host_res->dw_mem_base[4]) > iounmap((void *)host_res->dw_mem_base[4]); >- if (host_res->dw_wd_timer_dsp_base) >- iounmap(host_res->dw_wd_timer_dsp_base); > if (host_res->dw_dmmu_base) > iounmap(host_res->dw_dmmu_base); > if (host_res->dw_per_base) >@@ -923,7 +921,6 @@ static dsp_status request_bridge_resources(u32 >dw_context, s32 bRequest) > host_res->dw_mem_base[2] = (u32) NULL; > host_res->dw_mem_base[3] = (u32) NULL; > host_res->dw_mem_base[4] = (u32) NULL; >- host_res->dw_wd_timer_dsp_base = NULL; > host_res->dw_dmmu_base = NULL; > host_res->dw_sys_ctrl_base = NULL; > >@@ -956,8 +953,6 @@ static dsp_status request_bridge_resources(u32 >dw_context, s32 bRequest) > host_res->dw_mem_base[3]); > dev_dbg(bridge, "dw_prm_base %p\n", host_res->dw_prm_base); > dev_dbg(bridge, "dw_cm_base %p\n", host_res->dw_cm_base); >- dev_dbg(bridge, "dw_wd_timer_dsp_base %p\n", >- host_res->dw_wd_timer_dsp_base); > dev_dbg(bridge, "dw_dmmu_base %p\n", host_res- >>dw_dmmu_base); > > /* for 24xx base port is not mapping the mamory for DSP >@@ -1032,7 +1027,6 @@ static dsp_status request_bridge_resources_dsp(u32 >dw_context, s32 bRequest) > >OMAP_CORE_PRM_SIZE); > host_res->dw_dmmu_base = ioremap(OMAP_DMMU_BASE, > OMAP_DMMU_SIZE); >- host_res->dw_wd_timer_dsp_base = NULL; > > dev_dbg(bridge, "dw_mem_base[0] 0x%x\n", > host_res->dw_mem_base[0]); >@@ -1046,8 +1040,6 @@ static dsp_status request_bridge_resources_dsp(u32 >dw_context, s32 bRequest) > host_res->dw_mem_base[4]); > dev_dbg(bridge, "dw_prm_base %p\n", host_res->dw_prm_base); > dev_dbg(bridge, "dw_cm_base %p\n", host_res->dw_cm_base); >- dev_dbg(bridge, "dw_wd_timer_dsp_base %p\n", >- host_res->dw_wd_timer_dsp_base); > dev_dbg(bridge, "dw_dmmu_base %p\n", host_res- >>dw_dmmu_base); > dw_buff_size = sizeof(shm_size); > status = >diff --git a/drivers/dsp/bridge/rmgr/proc.c >b/drivers/dsp/bridge/rmgr/proc.c >index 1556285..2892041 100644 >--- a/drivers/dsp/bridge/rmgr/proc.c >+++ b/drivers/dsp/bridge/rmgr/proc.c >@@ -1149,8 +1149,9 @@ dsp_status proc_register_notify(void *hprocessor, u32 >event_mask, > } > /* Check if event mask is a valid processor related event */ > if (event_mask & ~(DSP_PROCESSORSTATECHANGE | DSP_PROCESSORATTACH | >- DSP_PROCESSORDETACH | DSP_PROCESSORRESTART | >- DSP_MMUFAULT | DSP_SYSERROR | DSP_PWRERROR)) >+ DSP_PROCESSORDETACH | DSP_PROCESSORRESTART | >+ DSP_MMUFAULT | DSP_SYSERROR | DSP_PWRERROR | >+ DSP_WDTOVERFLOW)) > status = DSP_EVALUE; > > /* Check if notify type is valid */ >@@ -1161,7 +1162,8 @@ dsp_status proc_register_notify(void *hprocessor, u32 >event_mask, > /* If event mask is not DSP_SYSERROR, DSP_MMUFAULT, > * or DSP_PWRERROR then register event immediately. */ > if (event_mask & >- ~(DSP_SYSERROR | DSP_MMUFAULT | DSP_PWRERROR)) { >+ ~(DSP_SYSERROR | DSP_MMUFAULT | DSP_PWRERROR | >+ DSP_WDTOVERFLOW)) { > status = ntfy_register(p_proc_object->ntfy_obj, > hnotification, event_mask, > notify_type); >diff --git a/drivers/dsp/bridge/wmd/io_sm.c >b/drivers/dsp/bridge/wmd/io_sm.c >index 1b5d977..545cca0 100644 >--- a/drivers/dsp/bridge/wmd/io_sm.c >+++ b/drivers/dsp/bridge/wmd/io_sm.c >@@ -51,6 +51,7 @@ > #include <dspbridge/wmddeh.h> > #include <dspbridge/wmdio.h> > #include <dspbridge/wmdioctl.h> >+#include <dspbridge/wdt.h> > #include <_tiomap.h> > #include <tiomap_io.h> > #include <_tiomap_pwr.h> >@@ -244,6 +245,8 @@ dsp_status bridge_io_create(OUT struct io_mgr >**phIOMgr, > if (DSP_SUCCEEDED(status)) { > pio_mgr->hwmd_context = hwmd_context; > pio_mgr->shared_irq = pMgrAttrs->irq_shared; >+ if (dsp_wdt_init()) >+ status = DSP_EFAIL; > } else { > status = CHNL_E_ISR; > } >@@ -279,6 +282,7 @@ dsp_status bridge_io_destroy(struct io_mgr *hio_mgr) > #ifndef DSP_TRACEBUF_DISABLED > kfree(hio_mgr->pmsg); > #endif >+ dsp_wdt_exit(); > /* Free this IO manager object */ > MEM_FREE_OBJECT(hio_mgr); > } else { >diff --git a/drivers/dsp/bridge/wmd/tiomap3430.c >b/drivers/dsp/bridge/wmd/tiomap3430.c >index ed51875..7a1093c 100644 >--- a/drivers/dsp/bridge/wmd/tiomap3430.c >+++ b/drivers/dsp/bridge/wmd/tiomap3430.c >@@ -60,6 +60,7 @@ > #include <dspbridge/dev.h> > #include <dspbridge/wcd.h> > #include <dspbridge/dmm.h> >+#include <dspbridge/wdt.h> > > /* ----------------------------------- Local */ > #include "_tiomap.h" >@@ -724,6 +725,10 @@ static dsp_status bridge_brd_start(struct >wmd_dev_context *hDevContext, > if (!wait_for_start(dev_context, dw_sync_addr)) > status = WMD_E_TIMEOUT; > >+ /* Start wdt */ >+ dsp_wdt_sm_set((void *)ul_shm_base); >+ dsp_wdt_enable(true); >+ > status = dev_get_io_mgr(dev_context->hdev_obj, &hio_mgr); > if (DSP_SUCCEEDED(status)) { > io_sh_msetting(hio_mgr, SHM_OPPINFO, NULL); >@@ -799,6 +804,8 @@ static dsp_status bridge_brd_stop(struct >wmd_dev_context *hDevContext) > > dev_context->dw_brd_state = BRD_STOPPED; /* update board >state */ > >+ dsp_wdt_enable(false); >+ > /* This is a good place to clear the MMU page tables as well */ > if (dev_context->pt_attrs) { > pt_attrs = dev_context->pt_attrs; >diff --git a/drivers/dsp/bridge/wmd/tiomap3430_pwr.c >b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c >index 9174a80..f21be4b 100644 >--- a/drivers/dsp/bridge/wmd/tiomap3430_pwr.c >+++ b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c >@@ -41,6 +41,7 @@ > > /* ----------------------------------- Mini Driver */ > #include <dspbridge/wmddeh.h> >+#include <dspbridge/wdt.h> > > /* ----------------------------------- specific to this file */ > #include "_tiomap.h" >@@ -125,6 +126,9 @@ dsp_status handle_hibernation_from_dsp(struct >wmd_dev_context *dev_context) > /* Turn off DSP Peripheral clocks and DSP Load monitor >timer */ > status = dsp_peripheral_clocks_disable(dev_context, NULL); > >+ /* Disable wdt on hibernation. */ >+ dsp_wdt_enable(false); >+ > if (DSP_SUCCEEDED(status)) { > /* Update the Bridger Driver state */ > dev_context->dw_brd_state = BRD_DSP_HIBERNATION; >@@ -239,6 +243,9 @@ dsp_status sleep_dsp(struct wmd_dev_context >*dev_context, IN u32 dw_cmd, > else > dev_context->dw_brd_state = BRD_RETENTION; > >+ /* Disable wdt on hibernation. */ >+ dsp_wdt_enable(false); >+ > /* Turn off DSP Peripheral clocks */ > status = dsp_peripheral_clocks_disable(dev_context, NULL); > if (DSP_FAILED(status)) { >diff --git a/drivers/dsp/bridge/wmd/tiomap_io.c >b/drivers/dsp/bridge/wmd/tiomap_io.c >index b5504a9..728db33 100644 >--- a/drivers/dsp/bridge/wmd/tiomap_io.c >+++ b/drivers/dsp/bridge/wmd/tiomap_io.c >@@ -30,6 +30,7 @@ > /* ----------------------------------- OS Adaptation Layer */ > #include <dspbridge/mem.h> > #include <dspbridge/cfg.h> >+#include <dspbridge/wdt.h> > > /* ----------------------------------- specific to this file */ > #include "_tiomap.h" >@@ -426,6 +427,7 @@ dsp_status sm_interrupt_dsp(struct wmd_dev_context >*dev_context, u16 mb_val) > #endif > /* Restart the peripheral clocks */ > dsp_peripheral_clocks_enable(dev_context, NULL); >+ dsp_wdt_enable(true); > > /* > * 2:0 AUTO_IVA2_DPLL - Enabling IVA2 DPLL auto control >diff --git a/drivers/dsp/bridge/wmd/ue_deh.c >b/drivers/dsp/bridge/wmd/ue_deh.c >index 14dd8ae..75a62b0 100644 >--- a/drivers/dsp/bridge/wmd/ue_deh.c >+++ b/drivers/dsp/bridge/wmd/ue_deh.c >@@ -39,6 +39,7 @@ > /* ----------------------------------- Platform Manager */ > #include <dspbridge/dev.h> > #include <dspbridge/wcd.h> >+#include <dspbridge/wdt.h> > > /* ------------------------------------ Hardware Abstraction Layer */ > #include <hw_defs.h> >@@ -281,6 +282,13 @@ void bridge_deh_notify(struct deh_mgr *hdeh_mgr, u32 >ulEventMask, u32 dwErrInfo) > "= 0x%x\n", dwErrInfo); > break; > #endif /* CONFIG_BRIDGE_NTFY_PWRERR */ >+ case DSP_WDTOVERFLOW: >+ deh_mgr_obj->err_info.dw_err_mask = >DSP_WDTOVERFLOW; >+ deh_mgr_obj->err_info.dw_val1 = 0L; >+ deh_mgr_obj->err_info.dw_val2 = 0L; >+ deh_mgr_obj->err_info.dw_val3 = 0L; >+ pr_err("bridge_deh_notify: DSP_WDTOVERFLOW \n "); >+ break; > default: > dev_dbg(bridge, "%s: Unknown Error, err_info = >0x%x\n", > __func__, dwErrInfo); >@@ -301,6 +309,11 @@ void bridge_deh_notify(struct deh_mgr *hdeh_mgr, u32 >ulEventMask, u32 dwErrInfo) > (void)dsp_peripheral_clocks_disable(dev_context, NULL); > /* Call DSP Trace Buffer */ > print_dsp_trace_buffer(hdeh_mgr->hwmd_context); >+ /* >+ * Avoid the subsequent WDT if it happens once, >+ * also If fatal error occurs >+ */ >+ dsp_wdt_enable(false); > > } > } >diff --git a/drivers/dsp/bridge/wmd/wdt.c b/drivers/dsp/bridge/wmd/wdt.c >new file mode 100644 >index 0000000..7a007f2 >--- /dev/null >+++ b/drivers/dsp/bridge/wmd/wdt.c >@@ -0,0 +1,148 @@ >+/* >+ * wdt.c >+ * >+ * DSP-BIOS Bridge driver support functions for TI OMAP processors. >+ * >+ * IO dispatcher for a shared memory channel driver. >+ * >+ * Copyright (C) 2010 Texas Instruments, Inc. >+ * >+ * This package is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License version 2 as >+ * published by the Free Software Foundation. >+ * >+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR >+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED >+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. >+ */ >+ >+#include <dspbridge/std.h> >+#include <dspbridge/dbdefs.h> >+#include <dspbridge/errbase.h> >+#include <dspbridge/wmddeh.h> >+#include <dspbridge/dev.h> >+#include <dspbridge/_chnl_sm.h> >+#include <dspbridge/wdt.h> >+#include <dspbridge/host_os.h> >+ >+ >+#ifdef CONFIG_BRIDGE_WDT3 >+static struct dsp_wdt_setting dsp_wdt; >+ >+void dsp_wdt_dpc(unsigned long data) >+{ >+ struct deh_mgr *deh_mgr; >+ dev_get_deh_mgr(dev_get_first(), &deh_mgr); >+ if (deh_mgr) >+ bridge_deh_notify(deh_mgr, DSP_WDTOVERFLOW, 0); >+} >+ >+irqreturn_t dsp_wdt_isr(int irq, void *data) >+{ >+ u32 value; >+ /* ack wdt3 interrupt */ >+ value = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET); >+ __raw_writel(value, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET); >+ >+ tasklet_schedule(&dsp_wdt.wdt3_tasklet); >+ return IRQ_HANDLED; >+} >+ >+int dsp_wdt_init(void) >+{ >+ int ret = 0; >+ >+ dsp_wdt.sm_wdt = NULL; >+ dsp_wdt.reg_base = OMAP2_L4_IO_ADDRESS(OMAP34XX_WDT3_BASE); >+ tasklet_init(&dsp_wdt.wdt3_tasklet, dsp_wdt_dpc, 0); >+ >+ dsp_wdt.fclk = clk_get(NULL, "wdt3_fck"); >+ >+ if (dsp_wdt.fclk) { >+ dsp_wdt.iclk = clk_get(NULL, "wdt3_ick"); >+ if (!dsp_wdt.iclk) { >+ clk_put(dsp_wdt.fclk); >+ dsp_wdt.fclk = NULL; >+ ret = -EFAULT; >+ } >+ } else >+ ret = -EFAULT; >+ >+ if (!ret) >+ ret = request_irq(INT_34XX_WDT3_IRQ, dsp_wdt_isr, 0, >+ "dsp_wdt", >&dsp_wdt); >+ >+ /* Disable at this moment, it will be enabled when DSP starts */ >+ if (!ret) >+ disable_irq(INT_34XX_WDT3_IRQ); >+ >+ return ret; >+} >+ >+void dsp_wdt_sm_set(void *data) >+{ >+ dsp_wdt.sm_wdt = data; >+ dsp_wdt.sm_wdt->wdt_overflow = CONFIG_WDT_TIMEOUT; >+} >+ >+ >+void dsp_wdt_exit(void) >+{ >+ free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt); >+ tasklet_kill(&dsp_wdt.wdt3_tasklet); >+ >+ if (dsp_wdt.fclk) >+ clk_put(dsp_wdt.fclk); >+ if (dsp_wdt.iclk) >+ clk_put(dsp_wdt.iclk); >+ >+ dsp_wdt.fclk = NULL; >+ dsp_wdt.iclk = NULL; >+ dsp_wdt.sm_wdt = NULL; >+ dsp_wdt.reg_base = NULL; >+} >+ >+void dsp_wdt_enable(bool enable) >+{ >+ u32 tmp; >+ static bool wdt_enable; >+ >+ if (wdt_enable == enable || !dsp_wdt.fclk || !dsp_wdt.iclk) >+ return; >+ >+ wdt_enable = enable; >+ >+ if (enable) { >+ clk_enable(dsp_wdt.fclk); >+ clk_enable(dsp_wdt.iclk); >+ dsp_wdt.sm_wdt->wdt_setclocks = 1; >+ tmp = __raw_readl(dsp_wdt.reg_base + >OMAP3_WDT3_ISR_OFFSET); >+ __raw_writel(tmp, dsp_wdt.reg_base + >OMAP3_WDT3_ISR_OFFSET); >+ enable_irq(INT_34XX_WDT3_IRQ); >+ } else { >+ disable_irq(INT_34XX_WDT3_IRQ); >+ dsp_wdt.sm_wdt->wdt_setclocks = 0; >+ clk_disable(dsp_wdt.iclk); >+ clk_disable(dsp_wdt.fclk); >+ } >+} >+ >+#else >+void dsp_wdt_enable(bool enable) >+{ >+} >+ >+void dsp_wdt_sm_set(void *data) >+{ >+} >+ >+int dsp_wdt_init(void) >+{ >+ return 0; >+} >+ >+void dsp_wdt_exit(void) >+{ >+} >+#endif >+ >-- >1.6.0.4 > >-- >To unsubscribe from this list: send the line "unsubscribe linux-omap" in >the body of a message to majord...@vger.kernel.org >More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html