summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 10c6439)
raw | patch | inline | side by side (parent: 10c6439)
author | vwan@ti.com <vwan@ti.com> | |
Wed, 28 May 2014 20:21:48 +0000 (13:21 -0700) | ||
committer | Robert Tivy <rtivy@ti.com> | |
Wed, 28 May 2014 20:43:45 +0000 (13:43 -0700) |
This commit adds QNX support for watchdog timer interrupts. The resource
manager schedules recovery whenever an interrupt from GPTimer 4 or 9
is received.
Only one of IPU1 or IPU2 can use watchdog timers.
Signed-off-by: VW <vwan@ti.com>
manager schedules recovery whenever an interrupt from GPTimer 4 or 9
is received.
Only one of IPU1 or IPU2 can use watchdog timers.
Signed-off-by: VW <vwan@ti.com>
diff --git a/qnx/src/ipc3x_dev/ti/syslink/family/vayu/gptimers.c b/qnx/src/ipc3x_dev/ti/syslink/family/vayu/gptimers.c
index 1df5a00840c3d0bce3933a222e83a88f98e2d0e6..1789984df82df6ee3ae64825800c49b0bab5da0f 100644 (file)
/* Standard headers */
#include <ti/syslink/Std.h>
-/*QNX specific header include */
+/* QNX specific header include */
#include <errno.h>
#include <unistd.h>
#include <stdbool.h>
#include <hw/inout.h>
#include <sys/mman.h>
+#include <OsalIsr.h>
+#include <ti/syslink/ProcMgr.h>
+#include <ti/syslink/utils/Trace.h>
+#include <MultiProc.h>
+#include <_MultiProc.h>
#include <gptimers.h>
#define CM_IPU_TIMER7_CLKCTRL_OFFSET 0x68
#define CM_IPU_TIMER8_CLKCTRL_OFFSET 0x70
+/* Timer base addresses and size */
+#define GPTIMER4_BASE 0x48036000
+#define GPTIMER9_BASE 0x4803E000
+#define TIMER_REG_SIZE 0x1000
+
+/*
+ * Interrupts for GPTimers used as watchdog
+ * They correspond to MPU_IRQ numbers + 32
+ */
+#define VAYU_IRQ_GPT4 (40 + 32)
+#define VAYU_IRQ_GPT9 (45 + 32)
+
+typedef enum {
+ GPTIMER_4 = 0,
+ GPTIMER_9,
+ GPTIMER_MAX
+} gpt_Nums;
+
+/* GPTimer registers */
+typedef struct gpt_Regs {
+ uint32_t tidr;
+ uint32_t space[3];
+ uint32_t tiocp_cfg;
+ uint32_t space1[3];
+ uint32_t eoi;
+ uint32_t irqstatus_raw;
+ uint32_t irqstatus;
+ uint32_t irqenable_set;
+ uint32_t irqenable_clr;
+ uint32_t irqwakeen;
+ uint32_t tclr;
+ uint32_t tcrr;
+ uint32_t tldr;
+ uint32_t ttgr;
+ uint32_t twps;
+ uint32_t tmar;
+ uint32_t tcar1;
+ uint32_t tsicr;
+ uint32_t tcar2;
+ uint32_t tpir;
+ uint32_t tnir;
+ uint32_t tcvr;
+ uint32_t tocr;
+ uint32_t towr;
+} gpt_Regs;
+
/*
* Defines the state object, which contains all the module
* specific information.
/* base address to CM_CORE_AON__IPU */
bool isSetup;
/* Indicates whether the ipu_pm module is setup. */
+ OsalIsr_Handle gpt4IsrObject;
+ /* ISR handle for gpt4 WDT */
+ OsalIsr_Handle gpt9IsrObject;
+ /* ISR handle for gpt9 WDT */
+ void * gpt4BaseAddr;
+ /* Base address of GPTimer 4 registers */
+ void * gpt9BaseAddr;
+ /* Base address of GPTimer 9 registers */
+ ProcMgr_Handle proc_handles[MultiProc_MAXPROCESSORS];
+ /* Array of processor handles */
};
static struct gpt_module_object gptState = {
int retval = EOK;
if (gptState.isSetup == false) {
+ gptState.isSetup = true;
+
gptState.cmCoreAonBaseVa = (uintptr_t)mmap_device_io(
CM_CORE_AON__IPU_SIZE, CM_CORE_AON__IPU_BASE);
if((uintptr_t)gptState.cmCoreAonBaseVa == MAP_DEVICE_FAILED) {
gpt_enable();
- gptState.isSetup = true;
+ gptState.gpt4BaseAddr = (void *)mmap_device_io(TIMER_REG_SIZE,
+ GPTIMER4_BASE);
+ if ((uintptr_t)gptState.gpt4BaseAddr == MAP_DEVICE_FAILED) {
+ retval = -ENOMEM;
+ gptState.gpt4BaseAddr = NULL;
+ goto exit;
+ }
+
+ gptState.gpt9BaseAddr = (void *)mmap_device_io(TIMER_REG_SIZE,
+ GPTIMER9_BASE);
+ if ((uintptr_t)gptState.gpt9BaseAddr == MAP_DEVICE_FAILED) {
+ retval = -ENOMEM;
+ gptState.gpt9BaseAddr = NULL;
+ goto exit;
+ }
}
exit:
if (retval != EOK) {
- gpt_disable();
-
- if (gptState.cmCoreAonBaseVa) {
- munmap((void *)gptState.cmCoreAonBaseVa, CM_CORE_AON__IPU_SIZE);
- gptState.cmCoreAonBaseVa = NULL;
- }
+ gpt_destroy();
}
return retval;
}
int gpt_destroy()
{
if (gptState.isSetup) {
+ if (gptState.gpt9BaseAddr) {
+ munmap((void *)gptState.gpt9BaseAddr, TIMER_REG_SIZE);
+ gptState.gpt9BaseAddr = NULL;
+ }
+
+ if (gptState.gpt4BaseAddr) {
+ munmap((void *)gptState.gpt4BaseAddr, TIMER_REG_SIZE);
+ gptState.gpt4BaseAddr = NULL;
+ }
+
gpt_disable();
if (gptState.cmCoreAonBaseVa) {
}
return EOK;
}
+
+/* Watchdog interrupt handler */
+static Bool gpt_interrupt(Ptr fxnArgs)
+{
+ int num;
+ /* Using IPU2's id since that is the offically supported IPU */
+ uint16_t ipu2_id = MultiProc_getId("IPU2");
+
+ /* Trigger recovery by setting the ProcMgr state */
+ switch ((uint32_t)fxnArgs) {
+ case GPTIMER_4:
+ num = 4;
+ ProcMgr_setState(gptState.proc_handles[ipu2_id],
+ ProcMgr_State_Watchdog);
+ break;
+ case GPTIMER_9:
+ num = 9;
+ ProcMgr_setState(gptState.proc_handles[ipu2_id],
+ ProcMgr_State_Watchdog);
+ break;
+ default:
+ num = 0;
+ break;
+ }
+
+ GT_1trace(curTrace, GT_4CLASS,
+ "ipu_pm_gptimer_interrupt: GPTimer %d expired!", num);
+
+ return 0;
+}
+
+/* Interrupt clear function*/
+static Bool gpt_clr_interrupt(Ptr fxnArgs)
+{
+ uintptr_t reg;
+ uint32_t num = (uint32_t)fxnArgs;
+ gpt_Regs *GPTRegs = NULL;
+
+ if (num == GPTIMER_4) {
+ GPTRegs = gptState.gpt4BaseAddr;
+ }
+ else if (num == GPTIMER_9) {
+ GPTRegs = gptState.gpt9BaseAddr;
+ }
+ else {
+ return TRUE;
+ }
+
+ reg = in32((uintptr_t)&GPTRegs->irqstatus);
+ reg |= 0x2;
+
+ /*Clear Overflow event */
+ out32((uintptr_t)&GPTRegs->irqstatus, reg);
+ reg = in32((uintptr_t)&GPTRegs->irqstatus);
+
+ /*Always return TRUE for ISR*/
+ return TRUE;
+}
+
+
+/* Wire the Watchdog interrupts to trigger recovery */
+int gpt_wdt_attach(int proc_id)
+{
+ int retval = EOK;
+ OsalIsr_Params isrParams;
+
+ if (proc_id > MultiProc_MAXPROCESSORS) {
+ return -EINVAL;
+ }
+
+ if ((proc_id == MultiProc_getId("IPU1")) ||
+ (proc_id == MultiProc_getId("IPU2"))) {
+ isrParams.checkAndClearFxn = gpt_clr_interrupt;
+ isrParams.fxnArgs = (Ptr)GPTIMER_9;
+ isrParams.intId = VAYU_IRQ_GPT9;
+ isrParams.sharedInt = FALSE;
+ gptState.gpt9IsrObject =
+ OsalIsr_create(&gpt_interrupt,
+ isrParams.fxnArgs, &isrParams);
+ if(gptState.gpt9IsrObject != NULL) {
+ if (OsalIsr_install(gptState.gpt9IsrObject) < 0) {
+ retval = -ENOMEM;
+ }
+ }
+ else {
+ retval = -ENOMEM;
+ }
+
+ isrParams.checkAndClearFxn = gpt_clr_interrupt;
+ isrParams.fxnArgs = (Ptr)GPTIMER_4;
+ isrParams.intId = VAYU_IRQ_GPT4;
+ isrParams.sharedInt = FALSE;
+ gptState.gpt4IsrObject =
+ OsalIsr_create(&gpt_interrupt,
+ isrParams.fxnArgs, &isrParams);
+ if(gptState.gpt4IsrObject != NULL) {
+ if (OsalIsr_install(gptState.gpt4IsrObject) < 0) {
+ retval = -ENOMEM;
+ }
+ }
+ else {
+ retval = -ENOMEM;
+ }
+ }
+
+ if ((retval >= 0) &&
+ (gptState.proc_handles[MultiProc_getId("IPU2")] == NULL)) {
+ /* Using IPU2's entry since it is the offically supported IPU */
+ retval = ProcMgr_open(&gptState.proc_handles[MultiProc_getId("IPU2")],
+ proc_id);
+ }
+ else {
+ if ((proc_id == MultiProc_getId("IPU1")) ||
+ (proc_id == MultiProc_getId("IPU2"))) {
+ if (gptState.gpt9IsrObject) {
+ OsalIsr_uninstall(gptState.gpt9IsrObject);
+ OsalIsr_delete(&gptState.gpt9IsrObject);
+ gptState.gpt9IsrObject = NULL;
+ }
+
+ if (gptState.gpt4IsrObject) {
+ OsalIsr_uninstall(gptState.gpt4IsrObject);
+ OsalIsr_delete(&gptState.gpt4IsrObject);
+ gptState.gpt4IsrObject = NULL;
+ }
+ }
+ }
+
+ return retval;
+}
+
+/* Un-hook the Watchdog interrupt handler */
+int gpt_wdt_detach(int proc_id)
+{
+ int retval = EOK;
+
+ if (proc_id > MultiProc_MAXPROCESSORS) {
+ return -EINVAL;
+ }
+
+ if ((proc_id == MultiProc_getId("IPU1")) ||
+ (proc_id == MultiProc_getId("IPU2"))) {
+ OsalIsr_uninstall(gptState.gpt9IsrObject);
+ OsalIsr_delete(&gptState.gpt9IsrObject);
+ gptState.gpt9IsrObject = NULL;
+
+ OsalIsr_uninstall(gptState.gpt4IsrObject);
+ OsalIsr_delete(&gptState.gpt4IsrObject);
+ gptState.gpt4IsrObject = NULL;
+ }
+
+ /* Using IPU2's entry since it is the offically supported IPU */
+ if (gptState.proc_handles[MultiProc_getId("IPU2")]) {
+ ProcMgr_close(&gptState.proc_handles[MultiProc_getId("IPU2")]);
+ gptState.proc_handles[MultiProc_getId("IPU2")] = NULL;
+ }
+
+ return retval;
+}
diff --git a/qnx/src/ipc3x_dev/ti/syslink/family/vayu/gptimers.h b/qnx/src/ipc3x_dev/ti/syslink/family/vayu/gptimers.h
index 5d9fa1656ee71c1e1f82579caa6828dfbd83b476..1370a42bce7f990aafa4b23011e355a348a49d17 100644 (file)
/* Disable GP timers */
int gpt_destroy();
+/* Wire the Watchdog interrupts to trigger recovery */
+int gpt_wdt_attach(int proc_id);
+
+/* Un-hook the Watchdog interrupt handler */
+int gpt_wdt_detach(int proc_id);
+
#if defined (__cplusplus)
}
#endif /* defined (__cplusplus) */
diff --git a/qnx/src/ipc3x_dev/ti/syslink/ipc/hlos/knl/Ipc.c b/qnx/src/ipc3x_dev/ti/syslink/ipc/hlos/knl/Ipc.c
index 3723e27eee5eb081022c8036c047afc8d7a61772..8a954098f88f9d7a6ef0da6738c120e60f648607 100644 (file)
/*
- * Copyright (c) 2008-2013, Texas Instruments Incorporated
+ * Copyright (c) 2008-2014, Texas Instruments Incorporated
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include <_MessageQCopy.h>
#include <ti/ipc/MessageQCopy.h>
+#if defined(SYSLINK_PLATFORM_VAYU)
+#include <gptimers.h>
+#endif
+
/* ----------------------------------- SysLink utils Headers */
#include <ti/syslink/inc/_MultiProc.h>
#include <ti/ipc/MultiProc.h>
ProcMgr_close(&procHandle);
}
-#if defined(SYSLINK_USE_IPU_PM)
+#if defined(SYSLINK_USE_IPU_PM) && defined(SYSLINK_PLATFORM_OMAP5)
if (status >= 0) {
status = ipu_pm_attach(remoteProcId);
if (status < 0) {
}
#endif
+#if defined(SYSLINK_PLATFORM_VAYU)
+ if (status >= 0) {
+ status = gpt_wdt_attach(remoteProcId);
+ if (status < 0) {
+ MessageQCopy_detach(remoteProcId);
+ }
+ }
+#endif
+
if (status >= 0) {
key = Gate_enterSystem ();
Ipc_module->procEntry[remoteProcId].isAttached++;
else {
Gate_leaveSystem (key);
-#if defined(SYSLINK_USE_IPU_PM)
+#if defined(SYSLINK_USE_IPU_PM) && defined(SYSLINK_PLATFORM_OMAP5)
status = ipu_pm_detach (remoteProcId);
#endif
+#if defined(SYSLINK_PLATFORM_VAYU)
+ status = gpt_wdt_detach(remoteProcId);
+#endif
+
status = MessageQCopy_detach (remoteProcId);
key = Gate_enterSystem ();