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..72558458ad9bba2663e77bfcef951e1bf6cd43bf 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>
/* Module mode mask */
#define MODULEMODE_MASK 0x3
+/* Masks for timer registers */
+#define GPT_TWPS_W_PEND_TCLR 0x1
+#define GPT_TCLR_STOP_MASK 0xfffffffe
+
/* Registers for clock management of timers in IPU power domain */
#define CM_CORE_AON__IPU_SIZE 0x100
#define CM_CORE_AON__IPU_BASE 0x4A005500
#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.
uintptr_t cmCoreAonBaseVa;
/* base address to CM_CORE_AON__IPU */
bool isSetup;
- /* Indicates whether the ipu_pm module is setup. */
+ /* Indicates whether the module is setup. */
+ bool isAttached;
+ /* Indicates whether the module is attached. */
+ 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,
+ "gpt_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;
+}
+
+/* Stop watchdog timer */
+static void gpt_wdt_stop(int num)
+{
+ uintptr_t reg;
+ gpt_Regs *GPTRegs = NULL;
+
+ if (num == GPTIMER_4) {
+ GPTRegs = gptState.gpt4BaseAddr;
+ }
+ else if (num == GPTIMER_9) {
+ GPTRegs = gptState.gpt9BaseAddr;
+ }
+ else {
+ return;
+ }
+
+ reg = in32((uintptr_t)&GPTRegs->tclr);
+ reg &= GPT_TCLR_STOP_MASK;
+
+ /* Clear Overflow event */
+ out32((uintptr_t)&GPTRegs->tclr, reg);
+
+ reg = in32((uintptr_t)&GPTRegs->twps);
+ while (reg & GPT_TWPS_W_PEND_TCLR) {
+ reg = in32((uintptr_t)&GPTRegs->twps);
+ }
+
+ /* Clear status bits */
+ reg = in32((uintptr_t)&GPTRegs->irqstatus);
+ if (reg) {
+ out32((uintptr_t)&GPTRegs->irqstatus, reg);
+ }
+}
+
+/* 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;
+ }
+
+ /* Only do the setup once since we only have two watchdog timers */
+ if (gptState.isAttached) {
+ return EOK;
+ }
+
+ if ((proc_id == MultiProc_getId("IPU1")) ||
+ (proc_id == MultiProc_getId("IPU2"))) {
+ gptState.isAttached = true;
+ 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) {
+ if (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 (gptState.isAttached) {
+ 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;
+ }
+
+ /*
+ * Stop the watchdog timers. We rely on the slave processors to
+ * start them, but on unload the host should stop them to avoid
+ * getting watchdog interrupts upon reload.
+ */
+ gpt_wdt_stop(GPTIMER_4);
+ gpt_wdt_stop(GPTIMER_9);
+
+ gptState.isAttached = false;
+ }
+ }
+
+ return retval;
+}