static int omap2_gp_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { omap_dm_timer_set_load_start(gptimer, 0, 0xffffffff - cycles); return 0; }
static void set_gptimer_pwm_vibrator(int on) { unsigned long flags; if (pwm_timer == NULL) { pr_err(KERN_ERR "vibrator pwm timer is NULL\n"); return; } spin_lock_irqsave(&vibe__timer_lock, flags); if (on) { if(!vibe_timer_state) { gpio_set_value(GPIO_VIB_EN, 1); omap_dm_timer_enable(pwm_timer); omap_dm_timer_set_match(pwm_timer, 1, 0xFFFFFFFE); omap_dm_timer_set_pwm(pwm_timer, 0, 1, OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE); omap_dm_timer_set_load_start(pwm_timer, 1, MOTOR_RESONANCE_COUTER_VALUE); vibe_timer_state = 1; } } else { if(vibe_timer_state) { omap_dm_timer_stop(pwm_timer); omap_dm_timer_disable(pwm_timer); gpio_set_value(GPIO_VIB_EN, 0); vibe_timer_state = 0; } } spin_unlock_irqrestore(&vibe__timer_lock, flags); }
static void omap2_gp_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { u32 period; omap_dm_timer_stop(gptimer); switch (mode) { case CLOCK_EVT_MODE_PERIODIC: period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ; period -= 1; omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - period); break; case CLOCK_EVT_MODE_ONESHOT: break; case CLOCK_EVT_MODE_SHUTDOWN: omap_timer_save_context(gptimer); break; case CLOCK_EVT_MODE_RESUME: omap_timer_restore_context(gptimer); break; case CLOCK_EVT_MODE_UNUSED: break; } }
/* Setup free-running counter for clocksource */ static void __init omap2_gp_clocksource_init(void) { static struct omap_dm_timer *gpt; u32 tick_rate, tick_period; static char err1[] __initdata = KERN_ERR "%s: failed to request dm-timer\n"; static char err2[] __initdata = KERN_ERR "%s: can't register clocksource!\n"; gpt = omap_dm_timer_request(); if (!gpt) printk(err1, clocksource_gpt.name); gpt_clocksource = gpt; omap_dm_timer_set_source(gpt, OMAP_TIMER_SRC_SYS_CLK); tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt)); tick_period = (tick_rate / HZ) - 1; omap_dm_timer_set_load_start(gpt, 1, 0); clocksource_gpt.mult = clocksource_khz2mult(tick_rate/1000, clocksource_gpt.shift); if (clocksource_register(&clocksource_gpt)) printk(err2, clocksource_gpt.name); }
static PVRSRV_ERROR AcquireGPTimer(SYS_SPECIFIC_DATA *psSysSpecData) { PVR_ASSERT(psSysSpecData->psGPTimer == NULL); /* * This code could try requesting registers 9, 10, and 11, * stopping at the first succesful request. We'll stick with * 11 for now, as it avoids having to hard code yet more * physical addresses into the code. */ psSysSpecData->psGPTimer = omap_dm_timer_request_specific(GPTIMER_TO_USE); if (psSysSpecData->psGPTimer == NULL) { PVR_DPF((PVR_DBG_WARNING, "%s: omap_dm_timer_request_specific failed", __FUNCTION__)); return PVRSRV_ERROR_CLOCK_REQUEST_FAILED; } /* Set timer source to system clock */ omap_dm_timer_set_source(psSysSpecData->psGPTimer, OMAP_TIMER_SRC_SYS_CLK); omap_dm_timer_enable(psSysSpecData->psGPTimer); /* Set autoreload, and start value of 0 */ omap_dm_timer_set_load_start(psSysSpecData->psGPTimer, 1, 0); omap_dm_timer_start(psSysSpecData->psGPTimer); /* * The DM timer API doesn't have a mechansim for obtaining the * physical address of the counter register. */ psSysSpecData->sTimerRegPhysBase.uiAddr = SYS_OMAP4430_GP11TIMER_REGS_SYS_PHYS_BASE; return PVRSRV_OK; }
static PVRSRV_ERROR AcquireGPTimer(SYS_SPECIFIC_DATA *psSysSpecData) { PVR_ASSERT(psSysSpecData->psGPTimer == NULL); psSysSpecData->psGPTimer = omap_dm_timer_request_specific(GPTIMER_TO_USE); if (psSysSpecData->psGPTimer == NULL) { PVR_DPF((PVR_DBG_WARNING, "%s: omap_dm_timer_request_specific failed", __FUNCTION__)); return PVRSRV_ERROR_CLOCK_REQUEST_FAILED; } omap_dm_timer_set_source(psSysSpecData->psGPTimer, OMAP_TIMER_SRC_SYS_CLK); omap_dm_timer_enable(psSysSpecData->psGPTimer); omap_dm_timer_set_load_start(psSysSpecData->psGPTimer, 1, 0); omap_dm_timer_start(psSysSpecData->psGPTimer); psSysSpecData->sTimerRegPhysBase.uiAddr = SYS_OMAP3_GPTIMER_REGS_SYS_PHYS_BASE; return PVRSRV_OK; }
/** * dsp_gpt_wait_overflow - set gpt overflow and wait for fixed timeout * @clk_id: GP Timer clock id. * @load: Overflow value. * * Sets an overflow interrupt for the desired GPT waiting for a timeout * of 5 msecs for the interrupt to occur. */ void dsp_gpt_wait_overflow(short int clk_id, unsigned int load) { struct omap_dm_timer *gpt = timer[clk_id - 1]; unsigned long timeout; if (!gpt) return; /* Enable overflow interrupt */ omap_dm_timer_set_int_enable(gpt, OMAP_TIMER_INT_OVERFLOW); /* * Set counter value to overflow counter after * one tick and start timer. */ omap_dm_timer_set_load_start(gpt, 0, load); /* Wait 80us for timer to overflow */ udelay(80); timeout = msecs_to_jiffies(5); /* Check interrupt status and wait for interrupt */ while (!(omap_dm_timer_read_status(gpt) & OMAP_TIMER_INT_OVERFLOW)) { if (time_is_after_jiffies(timeout)) { pr_err("%s: GPTimer interrupt failed\n", __func__); break; } } }
static int gptimer_start(void) { int err; u32 count = counter_config[0].count; BUG_ON(gptimer != NULL); /* First try to request timers from CORE power domain for OMAP3 */ if (cpu_is_omap34xx()) { gptimer = omap_dm_timer_request_specific(10); if (gptimer == NULL) gptimer = omap_dm_timer_request_specific(11); } /* Just any timer would be fine */ if (gptimer == NULL) gptimer = omap_dm_timer_request(); if (gptimer == NULL) return -ENODEV; omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ); err = request_irq(omap_dm_timer_get_irq(gptimer), gptimer_interrupt, IRQF_DISABLED, "oprofile gptimer", NULL); if (err) { omap_dm_timer_free(gptimer); gptimer = NULL; printk(KERN_ERR "oprofile: unable to request gptimer IRQ\n"); return err; } if (count < 1) count = 1; omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - count); omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW); return 0; }
static int __devinit cloudsurfer_wakeup_probe(struct platform_device *pdev) { struct cloudsurfer_wakeup_struct *wkup; struct input_dev *wkup_in; u32 tick_rate, cycles; int err; /* Data structure allocation */ wkup = kzalloc(sizeof(struct cloudsurfer_wakeup_struct), GFP_KERNEL); wkup_in = input_allocate_device(); if (!wkup_in) { printk("CLOUDSURFER - Can't allocate wakeup timer input\n"); err = -ENOMEM; goto error_input_dev; } /* Timer allocation and setup */ if ( (wkup->timer=omap_dm_timer_request_specific(1)) == NULL ) { printk("CLOUDSURFER - can't allocate wakeup timer\n"); err = -ENODEV; goto error_timer; } wkup->irq = omap_dm_timer_get_irq(wkup->timer); omap_dm_timer_set_source(wkup->timer,OMAP_TIMER_SRC_32_KHZ); tick_rate = clk_get_rate(omap_dm_timer_get_fclk(wkup->timer)); cycles = tick_rate * wakeup_seconds; omap_dm_timer_stop(wkup->timer); input_set_capability(wkup_in,EV_MSC,1); input_set_capability(wkup_in,EV_MSC,2); wkup_in->name = "cloudsurfer-wakeup"; wkup_in->phys = "cloudsurfer-wakeup/input0"; wkup_in->dev.parent = &pdev->dev; cloudsurfer_irq_data.dev_id = wkup_in; setup_irq(wkup->irq,&cloudsurfer_irq_data); input_set_drvdata(wkup_in, wkup); err = input_register_device(wkup_in); if (err) { printk("CLOUDSURFER -Can't register wakeup timer: %d\n", err); goto error_register; } omap_dm_timer_set_int_enable(wkup->timer,OMAP_TIMER_INT_OVERFLOW); omap_dm_timer_set_load_start(wkup->timer, 1, 0xffffffff - cycles); platform_set_drvdata(pdev, wkup_in); return 0; error_register: free_irq(wkup->irq, NULL); error_timer: input_free_device(wkup_in); error_input_dev: kfree(wkup); return err; }
static void __init omap2_gp_clockevent_init(void) { u32 tick_rate; int src; u32* time_base = ioremap(0x4A318000, SZ_4K); inited = 1; gptimer = omap_dm_timer_request_specific(gptimer_id); BUG_ON(gptimer == NULL); gptimer_wakeup = gptimer; #if defined(CONFIG_OMAP_32K_TIMER) src = OMAP_TIMER_SRC_32_KHZ; #else src = OMAP_TIMER_SRC_SYS_CLK; WARN(gptimer_id == 12, "WARNING: GPTIMER12 can only use the " "secure 32KiHz clock source\n"); #endif if (gptimer_id != 12) WARN(IS_ERR_VALUE(omap_dm_timer_set_source(gptimer, src)), "timer-gp: omap_dm_timer_set_source() failed\n"); tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer)); pr_info("OMAP clockevent source: GPTIMER%d at %u Hz\n", gptimer_id, tick_rate); print_timer(time_base); omap2_gp_timer_irq.dev_id = (void *)gptimer; //TODO: slow for safety omap_dm_timer_set_load_start(gptimer, 1, 0); print_timer(time_base); setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq); clockevent_gpt.mult = div_sc(tick_rate, NSEC_PER_SEC, clockevent_gpt.shift); clockevent_gpt.max_delta_ns = clockevent_delta2ns(0xffffffff, &clockevent_gpt); clockevent_gpt.min_delta_ns = clockevent_delta2ns(3, &clockevent_gpt); /* Timer internal resynch latency. */ clockevent_gpt.cpumask = cpumask_of(0); clockevents_register_device(&clockevent_gpt); omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW); print_timer(time_base); }
/*! ****************************************************************************** @Function AcquireGPTimer @Description Acquire a GP timer @Return PVRSRV_ERROR ******************************************************************************/ static PVRSRV_ERROR AcquireGPTimer(SYS_SPECIFIC_DATA *psSysSpecData) { PVR_ASSERT(psSysSpecData->psGPTimer == NULL); /* * This code has problems on module reload for OMAP5 running Linux * 3.4.10, due to omap2_dm_timer_set_src (called by * omap_dm_timer_request_specific), being unable to set the parent * clock to OMAP_TIMER_SRC_32_KHZ. * Not calling omap_dm_timer_set_source doesn't help. */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) || !defined(MODULE) /* * This code could try requesting registers 9, 10, and 11, * stopping at the first succesful request. We'll stick with * 11 for now, as it avoids having to hard code yet more * physical addresses into the code. */ psSysSpecData->psGPTimer = omap_dm_timer_request_specific(GPTIMER_TO_USE); if (psSysSpecData->psGPTimer == NULL) { PVR_DPF((PVR_DBG_WARNING, "%s: omap_dm_timer_request_specific failed", __FUNCTION__)); return PVRSRV_ERROR_CLOCK_REQUEST_FAILED; } omap_dm_timer_set_source(psSysSpecData->psGPTimer, OMAP_TIMER_SRC_SYS_CLK); omap_dm_timer_enable(psSysSpecData->psGPTimer); /* Set autoreload, and start value of 0 */ omap_dm_timer_set_load_start(psSysSpecData->psGPTimer, 1, 0); omap_dm_timer_start(psSysSpecData->psGPTimer); /* * The DM timer API doesn't have a mechanism for obtaining the * physical address of the counter register. */ psSysSpecData->sTimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_REGS_SYS_PHYS_BASE; #else /* (LINUX_VERSION_CODE <= KERNEL_VERSION(3,4,0)) || !defined(MODULE) */ (void)psSysSpecData; #endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(3,4,0)) || !defined(MODULE) */ return PVRSRV_OK; }
static int __init omap4_setup_gpt2(void) { /* Set up GPT2 for the WA */ gptimer2 = omap_dm_timer_request_specific(2); BUG_ON(gptimer2 == NULL); printk(KERN_INFO "Enabling AXI2OCP errata Fix \n"); omap_dm_timer_set_source(gptimer2, OMAP_TIMER_SRC_32_KHZ); gpt2_timer_irq.dev_id = (void *)gptimer2; setup_irq(omap_dm_timer_get_irq(gptimer2), &gpt2_timer_irq); omap_dm_timer_set_int_enable(gptimer2, OMAP_TIMER_INT_OVERFLOW); /* * Timer reload value is used based on mpu @ 600 MHz * And hence bridge is at 300 MHz. 65K cycle = 216 uS * 6 * 1/32 kHz => ~187 us */ omap_dm_timer_set_load_start(gptimer2, 1, 0xffffff06); return 0; }
static void omap2_gp_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { u32 period; omap_dm_timer_stop(gptimer); switch (mode) { case CLOCK_EVT_MODE_PERIODIC: period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ; period -= 1; if (cpu_is_omap44xx()) period = 0xff; /* FIXME: */ omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - period); break; case CLOCK_EVT_MODE_ONESHOT: break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_RESUME: break; } }
/* Setup free-running counter for clocksource */ static void __init omap2_gp_clocksource_init(void) { static struct omap_dm_timer *gpt; u32 tick_rate; static char err1[] __initdata = KERN_ERR "%s: failed to request dm-timer\n"; static char err2[] __initdata = KERN_ERR "%s: can't register clocksource!\n"; gpt = omap_dm_timer_request(); if (!gpt) printk(err1, clocksource_gpt.name); gpt_clocksource = gpt; omap_dm_timer_set_source(gpt, OMAP_TIMER_SRC_SYS_CLK); tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt)); omap_dm_timer_set_load_start(gpt, 1, 0); init_sched_clock(&cd, dmtimer_update_sched_clock, 32, tick_rate); if (clocksource_register_hz(&clocksource_gpt, tick_rate)) printk(err2, clocksource_gpt.name); }
int release_gptimer12(struct gptimer12_timer *timer) { int loop_count; int temp_count; int slot = -1; unsigned int next_time=0; int current_time; if ( gptimer12_count == 0 ) return -1; //printk ("\ntest 1 timer_instance_count : %d \n",gptimer12_count); for ( loop_count = 0; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if ( timer_manager[loop_count].timer.name != NULL) { if( strcmp( timer->name, timer_manager[loop_count].timer.name ) == 0 ) { slot = loop_count; break; } } } if ( slot == -1 ) return -1; // case : delete current working timer //CM_ICLKEN_WKUP |= 1 << 1; cm_val = cm_read_mod_reg( WKUP_MOD, CM_ICLKEN1 ); cm_val = cm_val | ( 1 << 1 ); cm_write_mod_reg( cm_val, WKUP_MOD, CM_ICLKEN1 ); if ( timer_manager[slot].remain_time == 0 ) { //current timer .. omap_dm_timer_stop( battery_timer ); current_time = GP_TIMER12_TICK_TO_SEC( 0xffffffff - omap_dm_timer_read_counter( battery_timer ) ); //printk("test1 current_time : %d\n",current_time); for ( loop_count = 0; loop_count < MAX_GPTIMER12_INSTANCE; loop_count++ ) { timer_manager[loop_count].remain_time += current_time; #if 0 if((timer_manager[loop_count].timer.name) != 0) { if((timer_manager[loop_count].remain_time) == 0) timer_manager[loop_count].remain_time = current_time; } #endif } } memset ( &( timer_manager[slot] ), 0, sizeof( struct gptimer12_manager ) ); gptimer12_count--; if( gptimer12_count < 0 ) gptimer12_count = 0; //printk("released : timer_instance_count : %d\n",gptimer12_count); if ( gptimer12_count == 0 ) { //printk("\n\n M timer empty .. \n"); prcm_wakeup_event_control( PRCM_GPT12, PRCM_DISABLE ); //egkim finish_gptimer12(); //egkim omap_dm_timer_disable( battery_timer ); //CM_ICLKEN_WKUP &= ~(1 << 1); cm_val = cm_read_mod_reg( WKUP_MOD, CM_ICLKEN1 ); cm_val = cm_val & ~( 1 << 1 ); cm_write_mod_reg( cm_val, WKUP_MOD,CM_ICLKEN1 ); /* change active state. */ timer->active = false; return 0; } for ( temp_count = 0 ; temp_count < MAX_GPTIMER12_INSTANCE ; temp_count++ ) { if( timer_manager[temp_count].timer.name != NULL ) { next_time = timer_manager[temp_count].remain_time; break; } } for ( temp_count = 0 ; temp_count < MAX_GPTIMER12_INSTANCE ; temp_count++ ) { if ( timer_manager[temp_count].timer.name != NULL ) { next_time = timer_manager[temp_count].remain_time; break; } } for ( loop_count = 0 ; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if( timer_manager[loop_count].timer.name != NULL ) { if ( next_time > timer_manager[loop_count].remain_time ) next_time = timer_manager[loop_count].remain_time; } } for ( loop_count = 0 ; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if( timer_manager[loop_count].timer.name != NULL ) timer_manager[loop_count].remain_time -= next_time; } printk( "\n\n\n next timeout : %d\n",next_time ); prcm_wakeup_event_control( PRCM_GPT12, PRCM_ENABLE ); omap_dm_timer_set_load_start( battery_timer, 0, 0xffffffff - GP_TIMER12_SEC_TO_TICK(next_time) ); //CM_ICLKEN_WKUP &= ~(1 << 1); cm_val = cm_read_mod_reg( WKUP_MOD, CM_ICLKEN1 ); cm_val = cm_val & ~( 1 << 1 ); cm_write_mod_reg( cm_val, WKUP_MOD,CM_ICLKEN1 ); timer->active = false; return 0; }
/* * ======== WMD_DEH_Notify ======== * DEH error notification function. Informs user about the error. */ void WMD_DEH_Notify(struct DEH_MGR *hDehMgr, u32 ulEventMask, u32 dwErrInfo) { struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr; struct WMD_DEV_CONTEXT *pDevContext; u32 memPhysical = 0; u32 HW_MMU_MAX_TLB_COUNT = 31; extern u32 faultAddr; u32 cnt = 0; if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) { printk(KERN_INFO "WMD_DEH_Notify: ********** DEVICE EXCEPTION " "**********\n"); pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext; switch (ulEventMask) { case DSP_SYSERROR: /* reset errInfo structure before use */ pDehMgr->errInfo.dwErrMask = DSP_SYSERROR; pDehMgr->errInfo.dwVal1 = 0L; pDehMgr->errInfo.dwVal2 = 0L; pDehMgr->errInfo.dwVal3 = 0L; pDehMgr->errInfo.dwVal1 = dwErrInfo; printk(KERN_ERR "WMD_DEH_Notify: DSP_SYSERROR, errInfo " "= 0x%x\n", dwErrInfo); dump_dl_modules(pDevContext); dump_dsp_stack(pDevContext); break; case DSP_MMUFAULT: /* MMU fault routine should have set err info * structure */ pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT; printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT," "errInfo = 0x%x\n", dwErrInfo); printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, High " "Address = 0x%x\n", (unsigned int)pDehMgr->errInfo.dwVal1); printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, Low " "Address = 0x%x\n", (unsigned int)pDehMgr->errInfo.dwVal2); printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, fault " "address = 0x%x\n", (unsigned int)faultAddr); PrintDspTraceBuffer(pDevContext); dump_dl_modules(pDevContext); dummyVaAddr = (u32)MEM_Calloc(sizeof(char) * 0x1000, MEM_PAGED); memPhysical = VirtToPhys(PG_ALIGN_LOW((u32)dummyVaAddr, PG_SIZE_4K)); pDevContext = (struct WMD_DEV_CONTEXT *) pDehMgr->hWmdContext; /* Reset the dynamic mmu index to fixed count if it * exceeds 31. So that the dynmmuindex is always * between the range of standard/fixed entries * and 31. */ if (pDevContext->numTLBEntries > HW_MMU_MAX_TLB_COUNT) { pDevContext->numTLBEntries = pDevContext-> fixedTLBEntries; } HW_MMU_TLBAdd(pDevContext->dwDSPMmuBase, memPhysical, faultAddr, HW_PAGE_SIZE_4KB, 1, &mapAttrs, HW_SET, HW_SET); /* * Send a GP Timer interrupt to DSP * The DSP expects a GP timer interrupt after an * MMU-Fault Request GPTimer */ if (timer) { 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 */ cnt = 0; while (!(omap_dm_timer_read_status(timer) & GPTIMER_IRQ_OVERFLOW)) { if (cnt++ >= GPTIMER_IRQ_WAIT_MAX_CNT) { pr_err("%s: GPTimer interrupt" " failed\n", __func__); break; } } } /* Clear MMU interrupt */ HW_MMU_EventAck(pDevContext->dwDSPMmuBase, HW_MMU_TRANSLATION_FAULT); dump_dsp_stack(hDehMgr->hWmdContext); if (timer) omap_dm_timer_disable(timer); break; #ifdef CONFIG_BRIDGE_NTFY_PWRERR case DSP_PWRERROR: /* reset errInfo structure before use */ pDehMgr->errInfo.dwErrMask = DSP_PWRERROR; pDehMgr->errInfo.dwVal1 = 0L; pDehMgr->errInfo.dwVal2 = 0L; pDehMgr->errInfo.dwVal3 = 0L; pDehMgr->errInfo.dwVal1 = dwErrInfo; printk(KERN_ERR "WMD_DEH_Notify: DSP_PWRERROR, errInfo " "= 0x%x\n", dwErrInfo); break; #endif /* CONFIG_BRIDGE_NTFY_PWRERR */ #ifdef CONFIG_BRIDGE_WDT3 case DSP_WDTOVERFLOW: pDehMgr->errInfo.dwErrMask = DSP_WDTOVERFLOW; pDehMgr->errInfo.dwVal1 = 0L; pDehMgr->errInfo.dwVal2 = 0L; pDehMgr->errInfo.dwVal3 = 0L; pr_err("WMD_DEH_Notify: DSP_WDTOVERFLOW \n "); break; #endif default: DBG_Trace(DBG_LEVEL6, "WMD_DEH_Notify: Unknown Error, errInfo = " "0x%x\n", dwErrInfo); break; } /* Filter subsequent notifications when an error occurs */ if (pDevContext->dwBrdState != BRD_ERROR) { NTFY_Notify(pDehMgr->hNtfy, ulEventMask); #ifdef CONFIG_BRIDGE_RECOVERY bridge_recover_schedule(); #endif } /* Set the Board state as ERROR */ pDevContext->dwBrdState = BRD_ERROR; /* Disable all the clocks that were enabled by DSP */ (void)DSP_PeripheralClocks_Disable(pDevContext, NULL); #ifdef CONFIG_BRIDGE_WDT3 /* * Avoid the subsequent WDT if it happens once, * also If MMU fault occurs */ dsp_wdt_enable(false); #endif } }
int request_gptimer12( struct gptimer12_timer *timer ) { int loop_count; int empty_slot = -1; unsigned int next_time = 0; unsigned int current_time = 0; //unsigned int temp; unsigned char update_flag = 0; // printk("request_gptimer12 called \n"); if ( gptimer12_count >= MAX_GPTIMER12_INSTANCE ) { printk( "Error... max gptimer12 instance" ); return -1; } //CM_ICLKEN_WKUP |= 1 << 1; cm_val = cm_read_mod_reg( WKUP_MOD, CM_ICLKEN1 ); cm_val = cm_val | ( 1 << 1 ); cm_write_mod_reg( cm_val, WKUP_MOD, CM_ICLKEN1 ); //modify exist entry for ( loop_count = 0; loop_count < MAX_GPTIMER12_INSTANCE; loop_count++ ) { if ( timer_manager[loop_count].timer.name != NULL ) { if( strcmp( timer_manager[loop_count].timer.name, timer->name ) == 0 ) { //printk("timer update \n"); memcpy( &( timer_manager[loop_count].timer ), timer, sizeof( struct gptimer12_timer ) ); timer_manager[loop_count].remain_time = timer->expire_time; update_flag = 1; } } } next_time = timer->expire_time; if ( update_flag == 0 ) { //add new entry for ( loop_count = 0; loop_count < MAX_GPTIMER12_INSTANCE; loop_count++ ) { if ( ( timer_manager[loop_count].timer.name ) == NULL ) { empty_slot = loop_count; break; } } //printk("empty_slot : %d, loop_count : %d\n",empty_slot,loop_count); if ( empty_slot == -1 ) { printk("Error.. No empty slot "); return -1; } gptimer12_count++; memcpy(&(timer_manager[empty_slot].timer),timer, sizeof(struct gptimer12_timer)); timer_manager[empty_slot].remain_time = timer->expire_time; // printk("test3 : gptimer12_count : %d\n",gptimer12_count); if ( gptimer12_count == 1 ) { omap_dm_timer_enable( battery_timer ); prcm_wakeup_event_control( PRCM_GPT12, PRCM_ENABLE ); omap_dm_timer_write_status( battery_timer, OMAP_TIMER_INT_OVERFLOW ); omap_dm_timer_set_int_enable( battery_timer, OMAP_TIMER_INT_OVERFLOW ); for ( loop_count = 0 ; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if ( timer_manager[loop_count].timer.name != NULL ) timer_manager[loop_count].remain_time -= next_time; } omap_dm_timer_set_load_start( battery_timer, 0, 0xffffffff - GP_TIMER12_SEC_TO_TICK(next_time) ); //CM_ICLKEN_WKUP &= ~(1 << 1); #if 0 cm_val = cm_read_mod_reg(WKUP_MOD,CM_ICLKEN1); cm_val = cm_val&~(1<<1); cm_write_mod_reg(cm_val,WKUP_MOD,CM_ICLKEN1); #endif timer->active = true; return 1; } } omap_dm_timer_stop( battery_timer ); //:commented this #if 1 current_time = GP_TIMER12_TICK_TO_SEC( 0xffffffff - omap_dm_timer_read_counter(battery_timer) ); #endif for ( loop_count = 0; loop_count < MAX_GPTIMER12_INSTANCE; loop_count++ ) { timer_manager[loop_count].remain_time += current_time; #if 0 if((timer_manager[loop_count].timer.name) != 0) { if((timer_manager[loop_count].remain_time) == 0) timer_manager[loop_count].remain_time = current_time; } #endif } for ( loop_count = 0 ; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if ( timer_manager[loop_count].timer.name != NULL ) { next_time = timer_manager[loop_count].remain_time; break; } } for ( loop_count = 0 ; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if ( timer_manager[loop_count].timer.name != NULL ) { if ( next_time > timer_manager[loop_count].remain_time ) next_time = timer_manager[loop_count].remain_time; } } for ( loop_count = 0 ; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if ( timer_manager[loop_count].timer.name != NULL ) timer_manager[loop_count].remain_time -= next_time; } // timer prcm_wakeup_event_control( PRCM_GPT12, PRCM_ENABLE ); omap_dm_timer_set_int_enable( battery_timer, OMAP_TIMER_INT_OVERFLOW ); omap_dm_timer_set_load_start( battery_timer, 0, 0xffffffff - GP_TIMER12_SEC_TO_TICK(next_time) ); //CM_ICLKEN_WKUP &= ~(1 << 1); #if 0 cm_val = cm_read_mod_reg(WKUP_MOD,CM_ICLKEN1); cm_val = cm_val&~(1<<1); cm_write_mod_reg(cm_val,WKUP_MOD,CM_ICLKEN1); // printk("requested gptimer12_count : %d \n",gptimer12_count); #endif timer->active = true; return 1; }
/* * ======== bridge_deh_notify ======== * DEH error notification function. Informs user about the error. */ void bridge_deh_notify(struct deh_mgr *hdeh_mgr, u32 ulEventMask, u32 dwErrInfo) { struct deh_mgr *deh_mgr_obj = (struct deh_mgr *)hdeh_mgr; struct wmd_dev_context *dev_context; int status = 0; u32 mem_physical = 0; u32 hw_mmu_max_tlb_count = 31; extern u32 fault_addr; struct cfg_hostres *resources; hw_status hw_status_obj; u32 cnt = 0; if (deh_mgr_obj) { printk(KERN_INFO "bridge_deh_notify: ********** DEVICE EXCEPTION " "**********\n"); dev_context = (struct wmd_dev_context *)deh_mgr_obj->hwmd_context; resources = dev_context->resources; switch (ulEventMask) { case DSP_SYSERROR: /* reset err_info structure before use */ deh_mgr_obj->err_info.dw_err_mask = DSP_SYSERROR; deh_mgr_obj->err_info.dw_val1 = 0L; deh_mgr_obj->err_info.dw_val2 = 0L; deh_mgr_obj->err_info.dw_val3 = 0L; deh_mgr_obj->err_info.dw_val1 = dwErrInfo; printk(KERN_ERR "bridge_deh_notify: DSP_SYSERROR, err_info " "= 0x%x\n", dwErrInfo); dump_dl_modules(dev_context); dump_dsp_stack(dev_context); break; case DSP_MMUFAULT: /* MMU fault routine should have set err info * structure */ deh_mgr_obj->err_info.dw_err_mask = DSP_MMUFAULT; printk(KERN_INFO "bridge_deh_notify: DSP_MMUFAULT," "err_info = 0x%x\n", dwErrInfo); printk(KERN_INFO "bridge_deh_notify: DSP_MMUFAULT, High " "Address = 0x%x\n", (unsigned int)deh_mgr_obj->err_info.dw_val1); printk(KERN_INFO "bridge_deh_notify: DSP_MMUFAULT, Low " "Address = 0x%x\n", (unsigned int)deh_mgr_obj->err_info.dw_val2); printk(KERN_INFO "bridge_deh_notify: DSP_MMUFAULT, fault " "address = 0x%x\n", (unsigned int)fault_addr); dummy_va_addr = (u32) kzalloc(sizeof(char) * 0x1000, GFP_ATOMIC); mem_physical = VIRT_TO_PHYS(PG_ALIGN_LOW ((u32) dummy_va_addr, PG_SIZE4K)); dev_context = (struct wmd_dev_context *) deh_mgr_obj->hwmd_context; print_dsp_trace_buffer(dev_context); dump_dl_modules(dev_context); /* Reset the dynamic mmu index to fixed count if it * exceeds 31. So that the dynmmuindex is always * between the range of standard/fixed entries * and 31. */ if (dev_context->num_tlb_entries > hw_mmu_max_tlb_count) { dev_context->num_tlb_entries = dev_context->fixed_tlb_entries; } if (DSP_SUCCEEDED(status)) { hw_status_obj = hw_mmu_tlb_add(resources->dw_dmmu_base, mem_physical, fault_addr, HW_PAGE_SIZE4KB, 1, &map_attrs, HW_SET, HW_SET); } /* * Send a GP Timer interrupt to DSP * The DSP expects a GP timer interrupt after an * MMU-Fault Request GPTimer */ if (timer) { 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 */ cnt = 0; while (!(omap_dm_timer_read_status(timer) & GPTIMER_IRQ_OVERFLOW)) { if (cnt++ >= GPTIMER_IRQ_WAIT_MAX_CNT) { pr_err("%s: GPTimer interrupt" " failed\n", __func__); break; } } } /* Clear MMU interrupt */ hw_mmu_event_ack(resources->dw_dmmu_base, HW_MMU_TRANSLATION_FAULT); dump_dsp_stack(deh_mgr_obj->hwmd_context); if (timer) omap_dm_timer_disable(timer); break; #ifdef CONFIG_BRIDGE_NTFY_PWRERR case DSP_PWRERROR: /* reset err_info structure before use */ deh_mgr_obj->err_info.dw_err_mask = DSP_PWRERROR; deh_mgr_obj->err_info.dw_val1 = 0L; deh_mgr_obj->err_info.dw_val2 = 0L; deh_mgr_obj->err_info.dw_val3 = 0L; deh_mgr_obj->err_info.dw_val1 = dwErrInfo; printk(KERN_ERR "bridge_deh_notify: DSP_PWRERROR, err_info " "= 0x%x\n", dwErrInfo); break; #endif /* CONFIG_BRIDGE_NTFY_PWRERR */ #ifdef CONFIG_BRIDGE_WDT3 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; #endif default: dev_dbg(bridge, "%s: Unknown Error, err_info = 0x%x\n", __func__, dwErrInfo); break; } /* Filter subsequent notifications when an error occurs */ if (dev_context->dw_brd_state != BRD_ERROR) { ntfy_notify(deh_mgr_obj->ntfy_obj, ulEventMask); #ifdef CONFIG_BRIDGE_RECOVERY bridge_recover_schedule(); #endif } /* Set the Board state as ERROR */ dev_context->dw_brd_state = BRD_ERROR; /* Disable all the clocks that were enabled by DSP */ (void)dsp_peripheral_clocks_disable(dev_context, NULL); #ifdef CONFIG_BRIDGE_WDT3 /* * Avoid the subsequent WDT if it happens once, * also If MMU fault occurs */ dsp_wdt_enable(false); #endif } }