static void omap2_pm_idle(void) { local_fiq_disable(); if (!omap2_can_sleep()) { if (omap_irq_pending()) goto out; omap2_enter_mpu_retention(); goto out; } if (omap_irq_pending()) goto out; omap2_enter_full_retention(); out: local_fiq_enable(); }
/** * omap3_enter_idle - Programs OMAP3 to enter the specified state * @dev: cpuidle device * @state: The target state to be programmed * * Called from the CPUidle framework to program the device to the * specified target state selected by the governor. */ static int omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) { struct omap3_processor_cx *cx = cpuidle_get_statedata(state); struct timespec ts_preidle, ts_postidle, ts_idle; u32 mpu_state = cx->mpu_state, core_state = cx->core_state; current_cx_state = *cx; /* Used to keep track of the total time in idle */ getnstimeofday(&ts_preidle); local_irq_disable(); local_fiq_disable(); pwrdm_set_next_pwrst(mpu_pd, mpu_state); pwrdm_set_next_pwrst(core_pd, core_state); if (omap_irq_pending() || need_resched()) goto return_sleep_time; if (cx->type == OMAP3_STATE_C1) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); } /* Execute ARM wfi */ omap_sram_idle(); if (cx->type == OMAP3_STATE_C1) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); } return_sleep_time: getnstimeofday(&ts_postidle); ts_idle = timespec_sub(ts_postidle, ts_preidle); local_irq_enable(); local_fiq_enable(); return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC; }
static void read_gpio_accurate (void) { int x = 0; struct timespec start_time, end_time, current_time; dbg(""); // IRQs will mess up our sample times so turn them off. local_irq_disable(); local_fiq_disable(); // time this bad boy getnstimeofday(&start_time); // get the data for the whole first 32 gpio pins & figure out what we want later for(x = 0; x < piScopinatorSampleSize; x++) { collected_data[x] = GPIO_READ_ALL; getnstimeofday(¤t_time); collection_times[x] = timespec_to_ns(¤t_time); } // end time getnstimeofday(&end_time); // even though the functions say nano seconds it won't really be nano second resolution since our pi // isn't that fast. Oh well collected_dataTime = timespec_to_ns(&end_time) - timespec_to_ns(&start_time); // don't forget to reactivate IRQ local_fiq_enable(); local_irq_enable(); // We are going to be outputting in pages so setting up a pointer and a // counter so we know when we are done. //dataPointer = (int*)&collected_data; data_pointer_count = 0; data_ready = 1; }
static int shmobile_cpuidle_enter(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { ktime_t before, after; before = ktime_get(); local_irq_disable(); local_fiq_disable(); shmobile_cpuidle_modes[index](); local_irq_enable(); local_fiq_enable(); after = ktime_get(); dev->last_residency = ktime_to_ns(ktime_sub(after, before)) >> 10; return index; }
/* * Let's power down on idle, but only if we are really * idle, because once we start down the path of * going idle we continue to do idle even if we get * a clock tick interrupt . . */ void omap1_pm_idle(void) { extern __u32 arm_idlect1_mask; __u32 use_idlect1 = arm_idlect1_mask; int do_sleep = 0; local_fiq_disable(); #if defined(CONFIG_OMAP_MPU_TIMER) && !defined(CONFIG_OMAP_DM_TIMER) #warning Enable 32kHz OS timer in order to allow sleep states in idle use_idlect1 = use_idlect1 & ~(1 << 9); #else if (enable_dyn_sleep) do_sleep = 1; #endif #ifdef CONFIG_OMAP_DM_TIMER use_idlect1 = omap_dm_timer_modify_idlect_mask(use_idlect1); #endif if (omap_dma_running()) use_idlect1 &= ~(1 << 6); /* We should be able to remove the do_sleep variable and multiple * tests above as soon as drivers, timer and DMA code have been fixed. * Even the sleep block count should become obsolete. */ if ((use_idlect1 != ~0) || !do_sleep) { __u32 saved_idlect1 = omap_readl(ARM_IDLECT1); if (cpu_is_omap15xx()) use_idlect1 &= OMAP1510_BIG_SLEEP_REQUEST; else use_idlect1 &= OMAP1610_IDLECT1_SLEEP_VAL; omap_writel(use_idlect1, ARM_IDLECT1); __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4"); omap_writel(saved_idlect1, ARM_IDLECT1); local_fiq_enable(); return; }
static int tegra114_idle_power_down(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { local_fiq_disable(); tegra_set_cpu_in_lp2(); cpu_pm_enter(); call_firmware_op(prepare_idle, TF_PM_MODE_LP2_NOFLUSH_L2); /* Do suspend by ourselves if the firmware does not implement it */ if (call_firmware_op(do_idle, 0) == -ENOSYS) cpu_suspend(0, tegra30_sleep_cpu_secondary_finish); cpu_pm_exit(); tegra_clear_cpu_in_lp2(); local_fiq_enable(); return index; }
static int tegra114_idle_power_down(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { local_fiq_disable(); tegra_set_cpu_in_lp2(); cpu_pm_enter(); clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu); cpu_suspend(0, tegra30_sleep_cpu_secondary_finish); clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); cpu_pm_exit(); tegra_clear_cpu_in_lp2(); local_fiq_enable(); return index; }
static int tegra_idle_enter_lp3(struct cpuidle_device *dev, struct cpuidle_state *state) { ktime_t enter, exit; s64 us; trace_power_start(POWER_CSTATE, 1, dev->cpu); local_irq_disable(); local_fiq_disable(); enter = ktime_get(); tegra_cpu_wfi(); exit = ktime_sub(ktime_get(), enter); us = ktime_to_us(exit); local_fiq_enable(); local_irq_enable(); return (int)us; }
static int tegra_suspend_enter(suspend_state_t state) { enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode(); if (WARN_ON(mode < TEGRA_SUSPEND_NONE || mode >= TEGRA_MAX_SUSPEND_MODE)) return -EINVAL; pr_info("Entering suspend state %s\n", lp_state[mode]); tegra_pmc_pm_set(mode); local_fiq_disable(); suspend_cpu_complex(); switch (mode) { case TEGRA_SUSPEND_LP2: tegra_set_cpu_in_lp2(); break; default: break; } cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu); switch (mode) { case TEGRA_SUSPEND_LP2: tegra_clear_cpu_in_lp2(); break; default: break; } restore_cpu_complex(); local_fiq_enable(); return 0; }
static inline void pnx4008_suspend(void) { void (*pnx4008_cpu_suspend_ptr) (void); local_irq_disable(); local_fiq_disable(); clk_disable(pll4_clk); __raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT)); __raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT)); /* make sure nothing gets suddenly written into SRAM - invalidate D cache. Meanwhile non-cacheable mapping to SRAM used here */ pnx4008_cache_clean_invalidate(); /*saving portion of SRAM to be used by suspend function. */ memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_suspend_sz); /*make sure SRAM copy gets physically written into SDRAM. SDRAM will be placed into self-refresh during power down */ pnx4008_cache_clean_invalidate(); /*copy suspend function into SRAM */ memcpy((void *)SRAM_VA, pnx4008_cpu_suspend, pnx4008_cpu_suspend_sz); /*do suspend */ pnx4008_cpu_suspend_ptr = (void *)SRAM_VA; pnx4008_cpu_suspend_ptr(); /*restoring portion of SRAM that was used by suspend function */ memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_suspend_sz); clk_enable(pll4_clk); local_fiq_enable(); local_irq_enable(); }
int __init mcpm_loopback(void (*cache_disable)(void)) { int ret; /* * We're going to soft-restart the current CPU through the * low-level MCPM code by leveraging the suspend/resume * infrastructure. Let's play it safe by using cpu_pm_enter() * in case the CPU init code path resets the VFP or similar. */ local_irq_disable(); local_fiq_disable(); ret = cpu_pm_enter(); if (!ret) { ret = cpu_suspend((unsigned long)cache_disable, nocache_trampoline); cpu_pm_exit(); } local_fiq_enable(); local_irq_enable(); if (ret) pr_err("%s returned %d\n", __func__, ret); return ret; }
static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu; bool entered_lp2 = false; if (tegra_pending_sgi()) ACCESS_ONCE_RW(abort_flag) = true; cpuidle_coupled_parallel_barrier(dev, &abort_barrier); if (abort_flag) { cpuidle_coupled_parallel_barrier(dev, &abort_barrier); abort_flag = false; /* clean flag for next coming */ return -EINTR; } local_fiq_disable(); tegra_set_cpu_in_lp2(cpu); cpu_pm_enter(); if (cpu == 0) entered_lp2 = tegra20_cpu_cluster_power_down(dev, drv, index); else entered_lp2 = tegra20_idle_enter_lp2_cpu_1(dev, drv, index); cpu_pm_exit(); tegra_clear_cpu_in_lp2(cpu); local_fiq_enable(); smp_rmb(); return entered_lp2 ? index : 0; }
static int secure_writer_monitor(void *arg) { struct secure_monitor_arg *parg = (struct secure_monitor_arg*)arg; unsigned char *pfbuf = parg->pfbuf; unsigned long flags; NS_SHARE_MEM_HEAD *pshead = (NS_SHARE_MEM_HEAD*)(parg->psbuf+SHARE_MEM_HEAD_OFFSET); unsigned char *psdata = parg->psbuf + SHARE_MEM_DATA_OFFSET; bool w_busy = false; while(1){ if(w_busy){ write_to_flash(pfbuf, FLASH_BUF_SIZE); w_busy=false; } //arch_local_irq_save(); local_fiq_disable(); lock_mutex(&(pshead->cmdlock)); if(pshead->cmd == SHARE_MEM_CMD_WRITE){ memcpy(pfbuf, psdata, FLASH_BUF_SIZE); pshead->cmd=SHARE_MEM_CMD_FREE; w_busy = true; printk("************kernel detect write flag*****\n"); } unlock_mutex(&(pshead->cmdlock)); //arch_local_irq_restore(flags); local_fiq_enable(); if(!w_busy){ if(kthread_should_stop()) break; else msleep(200); } } return 0; }
static int tegra_idle_enter_lp3(struct cpuidle_device *dev, struct cpuidle_state *state) { ktime_t enter, exit; s64 us; trace_power_start(POWER_CSTATE, 1, dev->cpu); local_irq_disable(); local_fiq_disable(); enter = ktime_get(); tegra_cpu_wfi(); exit = ktime_sub(ktime_get(), enter); us = ktime_to_us(exit); /* move from driver/cpuidle/cpuidle.c */ dev->states[0].usage++; dev->states[0].time += (unsigned long long)us; local_fiq_enable(); local_irq_enable(); return (int)us; }
/* * Let's power down on idle, but only if we are really * idle, because once we start down the path of * going idle we continue to do idle even if we get * a clock tick interrupt . . */ void omap_pm_idle(void) { unsigned int mask32 = 0; /* * If the DSP is being used let's just idle the CPU, the overhead * to wake up from Big Sleep is big, milliseconds versus micro * seconds for wait for interrupt. */ local_irq_disable(); local_fiq_disable(); if (need_resched()) { local_fiq_enable(); local_irq_enable(); return; } mask32 = omap_readl(ARM_SYSST); /* * Prevent the ULPD from entering low power state by setting * POWER_CTRL_REG:4 = 0 */ omap_writew(omap_readw(ULPD_POWER_CTRL) & ~ULPD_DEEP_SLEEP_TRANSITION_EN, ULPD_POWER_CTRL); /* * Since an interrupt may set up a timer, we don't want to * reprogram the hardware timer with interrupts enabled. * Re-enable interrupts only after returning from idle. */ timer_dyn_reprogram(); if ((mask32 & DSP_IDLE) == 0) { __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4"); } else
/** * omap3_enter_idle - Programs OMAP3 to enter the specified state * @dev: cpuidle device * @state: The target state to be programmed * * Called from the CPUidle framework to program the device to the * specified target state selected by the governor. */ static int omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) { struct omap3_processor_cx *cx = cpuidle_get_statedata(state); struct timespec ts_preidle, ts_postidle, ts_idle; u32 mpu_state = cx->mpu_state, core_state = cx->core_state, cam_state = 0, dss_state = 0, per_state = 0; /* modified for mp3 current -- begin */ u32 mpu_prev,core_prev =0 ; current_cx_state = *cx; int requested=cx->type; static int cam_deny = 0; u32 wkdep_per_value = 0; wkdep_per_value = omap_readl(0x483070C8); /* modified for mp3 current -- end*/ /* Used to keep track of the total time in idle */ getnstimeofday(&ts_preidle); local_irq_disable(); local_fiq_disable(); pwrdm_set_next_pwrst(mpu_pd, mpu_state); pwrdm_set_next_pwrst(core_pd, core_state); if (omap_irq_pending() || need_resched()) goto return_sleep_time; /* Keep CAM domain active during ISP usecases */ if(( front_cam_in_use || back_cam_in_use || (stream_on)) ){ pwrdm_for_each_clkdm(cam_pd, _cpuidle_deny_idle); cam_deny = 1 ; } /* if (cx->type == OMAP3_STATE_C1) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); } */ if (dss_suspend_flag && audio_on) { omap_writel(wkdep_per_value & ~(1<<1) ,0x483070C8 );//PM_WKDEP_PER } /* Execute ARM wfi */ omap_sram_idle(); /* if (cx->type == OMAP3_STATE_C1) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); } */ /* Keep CAM domain active during ISP usecases */ if(cam_deny){ pwrdm_for_each_clkdm(cam_pd, _cpuidle_allow_idle); cam_deny = 0; } if(!dss_suspend_flag){ omap_writel(wkdep_per_value, 0x483070C8); //PM_WKDEP_PER } core_state = pwrdm_read_prev_pwrst(core_pd); mpu_state = pwrdm_read_prev_pwrst(mpu_pd); cam_state = pwrdm_read_prev_pwrst(cam_pd); dss_state = pwrdm_read_prev_pwrst(dss_pd); per_state = pwrdm_read_prev_pwrst(per_pd); //printk(KERN_INFO "requested C%d, actual core=%d, mpu=%d cam = %d dss = %d per = %d \n", requested, core_state, mpu_state,cam_state); return_sleep_time: getnstimeofday(&ts_postidle); ts_idle = timespec_sub(ts_postidle, ts_preidle); /* modified for mp3 current -- begin */ mpu_prev = omap_readl(0x483069E8); mpu_prev = mpu_prev & 0x3 ; core_prev = omap_readl(0x48306AE8); core_prev = core_prev & 0x3 ; /* modified for mp3 current -- end */ local_irq_enable(); local_fiq_enable(); return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC; }
/* * This is the secondary CPU boot entry. We're using this CPUs * idle thread stack, but a set of temporary page tables. */ asmlinkage void __cpuinit secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); aee_rr_rec_hoplug(cpu, 1, 0); printk("CPU%u: Booted secondary processor\n", cpu); /* * All kernel threads share the same mm context; grab a * reference and switch to it. */ atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); aee_rr_rec_hoplug(cpu, 2, 0); set_my_cpu_offset(per_cpu_offset(smp_processor_id())); aee_rr_rec_hoplug(cpu, 3, 0); /* * TTBR0 is only used for the identity mapping at this stage. Make it * point to zero page to avoid speculatively fetching new entries. */ cpu_set_reserved_ttbr0(); aee_rr_rec_hoplug(cpu, 4, 0); flush_tlb_all(); aee_rr_rec_hoplug(cpu, 5, 0); preempt_disable(); aee_rr_rec_hoplug(cpu, 6, 0); trace_hardirqs_off(); aee_rr_rec_hoplug(cpu, 7, 0); if (cpu_ops[cpu]->cpu_postboot) cpu_ops[cpu]->cpu_postboot(); aee_rr_rec_hoplug(cpu, 8, 0); /* * OK, now it's safe to let the boot CPU continue. Wait for * the CPU migration code to notice that the CPU is online * before we continue. */ set_cpu_online(cpu, true); aee_rr_rec_hoplug(cpu, 9, 0); complete(&cpu_running); aee_rr_rec_hoplug(cpu, 10, 0); smp_store_cpu_info(cpu); aee_rr_rec_hoplug(cpu, 11, 0); /* * Enable GIC and timers. */ notify_cpu_starting(cpu); aee_rr_rec_hoplug(cpu, 12, 0); local_dbg_enable(); aee_rr_rec_hoplug(cpu, 13, 0); local_irq_enable(); aee_rr_rec_hoplug(cpu, 14, 0); local_fiq_enable(); aee_rr_rec_hoplug(cpu, 15, 0); /* * OK, it's off to the idle thread for us */ cpu_startup_entry(CPUHP_ONLINE); aee_rr_rec_hoplug(cpu, 16, 0); }
/** * omap3_enter_idle - Programs OMAP3 to enter the specified state * @dev: cpuidle device * @state: The target state to be programmed * * Called from the CPUidle framework to program the device to the * specified target state selected by the governor. */ static int omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) { struct omap3_idle_statedata *cx = cpuidle_get_statedata(state); struct timespec ts_preidle, ts_postidle, ts_idle; u32 mpu_state = cx->mpu_state, core_state = cx->core_state; /* Used to keep track of the total time in idle */ getnstimeofday(&ts_preidle); local_irq_disable(); local_fiq_disable(); pwrdm_set_next_pwrst(mpu_pd, mpu_state); pwrdm_set_next_pwrst(core_pd, core_state); if (omap_irq_pending() || need_resched()) goto return_sleep_time; /* S[, 20120922, [email protected], PM from froyo. */ #if defined(CONFIG_PRODUCT_LGE_LU6800) /* Deny idle for C1 */ if (te_cpu_idle_block == 1 || doing_wakeup == 1) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); } #else /* Deny idle for C1 */ if (state == &dev->states[0]) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); } #endif /* E], 20120922, [email protected], PM from froyo. */ /* Execute ARM wfi */ omap_sram_idle(false); /* S[, 20120922, [email protected], PM from froyo. */ #if defined(CONFIG_PRODUCT_LGE_LU6800) /* Re-allow idle for C1 */ if (te_cpu_idle_block == 1 || doing_wakeup == 1) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); } #else /* Re-allow idle for C1 */ if (state == &dev->states[0]) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); } #endif /* E], 20120922, [email protected], PM from froyo. */ return_sleep_time: getnstimeofday(&ts_postidle); ts_idle = timespec_sub(ts_postidle, ts_preidle); local_irq_enable(); local_fiq_enable(); return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC; }
/* * Power collapse the Apps processor. This function executes the handshake * protocol with Modem. * * Return value: * -EAGAIN: modem reset occurred or early exit from power collapse * -EBUSY: modem not ready for our power collapse -- no power loss * -ETIMEDOUT: timed out waiting for modem's handshake -- no power loss * 0: success */ static int msm_pm_power_collapse (bool from_idle, uint32_t sleep_delay, uint32_t sleep_limit) { struct msm_pm_polled_group state_grps[2]; unsigned long saved_acpuclk_rate; int collapsed = 0; int ret; int val; int modem_early_exit = 0; MSM_PM_DPRINTK(MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE, KERN_INFO, "%s(): idle %d, delay %u, limit %u\n", __func__, (int)from_idle, sleep_delay, sleep_limit); if (!(smsm_get_state(SMSM_POWER_MASTER_DEM) & DEM_MASTER_SMSM_READY)) { MSM_PM_DPRINTK( MSM_PM_DEBUG_SUSPEND | MSM_PM_DEBUG_POWER_COLLAPSE, KERN_INFO, "%s(): master not ready\n", __func__); ret = -EBUSY; goto power_collapse_bail; } memset(msm_pm_smem_data, 0, sizeof(*msm_pm_smem_data)); if (cpu_is_msm8625()) { /* Program the SPM */ ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_COLLAPSE, false); WARN_ON(ret); } /* Call CPR suspend only for "idlePC" case */ if (msm_cpr_ops && from_idle) msm_cpr_ops->cpr_suspend(); msm_pm_irq_extns->enter_sleep1(true, from_idle, &msm_pm_smem_data->irq_mask); msm_sirc_enter_sleep(); msm_gpio_enter_sleep(from_idle); msm_pm_smem_data->sleep_time = sleep_delay; msm_pm_smem_data->resources_used = sleep_limit; /* Enter PWRC/PWRC_SUSPEND */ if (from_idle) smsm_change_state(SMSM_APPS_DEM, DEM_SLAVE_SMSM_RUN, DEM_SLAVE_SMSM_PWRC); else smsm_change_state(SMSM_APPS_DEM, DEM_SLAVE_SMSM_RUN, DEM_SLAVE_SMSM_PWRC | DEM_SLAVE_SMSM_PWRC_SUSPEND); MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): PWRC"); MSM_PM_DEBUG_PRINT_SLEEP_INFO(); memset(state_grps, 0, sizeof(state_grps)); state_grps[0].group_id = SMSM_POWER_MASTER_DEM; state_grps[0].bits_all_set = DEM_MASTER_SMSM_RSA; state_grps[1].group_id = SMSM_MODEM_STATE; state_grps[1].bits_all_set = SMSM_RESET; ret = msm_pm_poll_state(ARRAY_SIZE(state_grps), state_grps); if (ret < 0) { printk(KERN_EMERG "%s(): power collapse entry " "timed out waiting for Modem's response\n", __func__); msm_pm_timeout(); } if (ret == 1) { MSM_PM_DPRINTK( MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE, KERN_INFO, "%s(): msm_pm_poll_state detected Modem reset\n", __func__); goto power_collapse_early_exit; } /* DEM Master in RSA */ MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): PWRC RSA"); ret = msm_pm_irq_extns->enter_sleep2(true, from_idle); if (ret < 0) { MSM_PM_DPRINTK( MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE, KERN_INFO, "%s(): msm_irq_enter_sleep2 aborted, %d\n", __func__, ret); goto power_collapse_early_exit; } msm_pm_config_hw_before_power_down(); MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): pre power down"); saved_acpuclk_rate = acpuclk_power_collapse(); MSM_PM_DPRINTK(MSM_PM_DEBUG_CLOCK, KERN_INFO, "%s(): change clock rate (old rate = %lu)\n", __func__, saved_acpuclk_rate); if (saved_acpuclk_rate == 0) { msm_pm_config_hw_after_power_up(); goto power_collapse_early_exit; } msm_pm_boot_config_before_pc(smp_processor_id(), virt_to_phys(msm_pm_collapse_exit)); #ifdef CONFIG_VFP if (from_idle) vfp_pm_suspend(); #endif #ifdef CONFIG_CACHE_L2X0 if (!cpu_is_msm8625()) l2cc_suspend(); else apps_power_collapse = 1; #endif collapsed = msm_pm_collapse(); /* * TBD: Currently recognise the MODEM early exit * path by reading the MPA5_GDFS_CNT_VAL register. */ if (cpu_is_msm8625()) { /* * on system reset, default value of MPA5_GDFS_CNT_VAL * is = 0x0, later modem reprogram this value to * 0x00030004. Once APPS did a power collapse and * coming out of it expected value of this register * always be 0x00030004. Incase if APPS sees the value * as 0x00030002 consider this case as a modem early * exit. */ val = __raw_readl(MSM_CFG_CTL_BASE + 0x38); if (val != 0x00030002) power_collapsed = 1; else modem_early_exit = 1; } #ifdef CONFIG_CACHE_L2X0 if (!cpu_is_msm8625()) l2cc_resume(); else apps_power_collapse = 0; #endif msm_pm_boot_config_after_pc(smp_processor_id()); if (collapsed) { #ifdef CONFIG_VFP if (from_idle) vfp_pm_resume(); #endif cpu_init(); local_fiq_enable(); } MSM_PM_DPRINTK(MSM_PM_DEBUG_SUSPEND | MSM_PM_DEBUG_POWER_COLLAPSE, KERN_INFO, "%s(): msm_pm_collapse returned %d\n", __func__, collapsed); MSM_PM_DPRINTK(MSM_PM_DEBUG_CLOCK, KERN_INFO, "%s(): restore clock rate to %lu\n", __func__, saved_acpuclk_rate); if (acpuclk_set_rate(smp_processor_id(), saved_acpuclk_rate, SETRATE_PC) < 0) printk(KERN_ERR "%s(): failed to restore clock rate(%lu)\n", __func__, saved_acpuclk_rate); msm_pm_irq_extns->exit_sleep1(msm_pm_smem_data->irq_mask, msm_pm_smem_data->wakeup_reason, msm_pm_smem_data->pending_irqs); msm_pm_config_hw_after_power_up(); MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): post power up"); memset(state_grps, 0, sizeof(state_grps)); state_grps[0].group_id = SMSM_POWER_MASTER_DEM; state_grps[0].bits_any_set = DEM_MASTER_SMSM_RSA | DEM_MASTER_SMSM_PWRC_EARLY_EXIT; state_grps[1].group_id = SMSM_MODEM_STATE; state_grps[1].bits_all_set = SMSM_RESET; ret = msm_pm_poll_state(ARRAY_SIZE(state_grps), state_grps); if (ret < 0) { printk(KERN_EMERG "%s(): power collapse exit " "timed out waiting for Modem's response\n", __func__); msm_pm_timeout(); } if (ret == 1) { MSM_PM_DPRINTK( MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE, KERN_INFO, "%s(): msm_pm_poll_state detected Modem reset\n", __func__); goto power_collapse_early_exit; } /* Sanity check */ if (collapsed && !modem_early_exit) { BUG_ON(!(state_grps[0].value_read & DEM_MASTER_SMSM_RSA)); } else { BUG_ON(!(state_grps[0].value_read & DEM_MASTER_SMSM_PWRC_EARLY_EXIT)); goto power_collapse_early_exit; } /* Enter WFPI */ smsm_change_state(SMSM_APPS_DEM, DEM_SLAVE_SMSM_PWRC | DEM_SLAVE_SMSM_PWRC_SUSPEND, DEM_SLAVE_SMSM_WFPI); MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): WFPI"); memset(state_grps, 0, sizeof(state_grps)); state_grps[0].group_id = SMSM_POWER_MASTER_DEM; state_grps[0].bits_all_set = DEM_MASTER_SMSM_RUN; state_grps[1].group_id = SMSM_MODEM_STATE; state_grps[1].bits_all_set = SMSM_RESET; ret = msm_pm_poll_state(ARRAY_SIZE(state_grps), state_grps); if (ret < 0) { printk(KERN_EMERG "%s(): power collapse WFPI " "timed out waiting for Modem's response\n", __func__); msm_pm_timeout(); } if (ret == 1) { MSM_PM_DPRINTK( MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE, KERN_INFO, "%s(): msm_pm_poll_state detected Modem reset\n", __func__); ret = -EAGAIN; goto power_collapse_restore_gpio_bail; } /* DEM Master == RUN */ MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): WFPI RUN"); MSM_PM_DEBUG_PRINT_SLEEP_INFO(); msm_pm_irq_extns->exit_sleep2(msm_pm_smem_data->irq_mask, msm_pm_smem_data->wakeup_reason, msm_pm_smem_data->pending_irqs); msm_pm_irq_extns->exit_sleep3(msm_pm_smem_data->irq_mask, msm_pm_smem_data->wakeup_reason, msm_pm_smem_data->pending_irqs); msm_gpio_exit_sleep(); msm_sirc_exit_sleep(); smsm_change_state(SMSM_APPS_DEM, DEM_SLAVE_SMSM_WFPI, DEM_SLAVE_SMSM_RUN); MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): RUN"); smd_sleep_exit(); if (cpu_is_msm8625()) { ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false); WARN_ON(ret); } /* Call CPR resume only for "idlePC" case */ if (msm_cpr_ops && from_idle) msm_cpr_ops->cpr_resume(); return 0; power_collapse_early_exit: /* Enter PWRC_EARLY_EXIT */ smsm_change_state(SMSM_APPS_DEM, DEM_SLAVE_SMSM_PWRC | DEM_SLAVE_SMSM_PWRC_SUSPEND, DEM_SLAVE_SMSM_PWRC_EARLY_EXIT); MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): EARLY_EXIT"); memset(state_grps, 0, sizeof(state_grps)); state_grps[0].group_id = SMSM_POWER_MASTER_DEM; state_grps[0].bits_all_set = DEM_MASTER_SMSM_PWRC_EARLY_EXIT; state_grps[1].group_id = SMSM_MODEM_STATE; state_grps[1].bits_all_set = SMSM_RESET; ret = msm_pm_poll_state(ARRAY_SIZE(state_grps), state_grps); MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): EARLY_EXIT EE"); if (ret < 0) { printk(KERN_EMERG "%s(): power collapse EARLY_EXIT " "timed out waiting for Modem's response\n", __func__); msm_pm_timeout(); } if (ret == 1) { MSM_PM_DPRINTK( MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE, KERN_INFO, "%s(): msm_pm_poll_state detected Modem reset\n", __func__); } /* DEM Master == RESET or PWRC_EARLY_EXIT */ ret = -EAGAIN; power_collapse_restore_gpio_bail: msm_gpio_exit_sleep(); msm_sirc_exit_sleep(); /* Enter RUN */ smsm_change_state(SMSM_APPS_DEM, DEM_SLAVE_SMSM_PWRC | DEM_SLAVE_SMSM_PWRC_SUSPEND | DEM_SLAVE_SMSM_PWRC_EARLY_EXIT, DEM_SLAVE_SMSM_RUN); MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): RUN"); if (collapsed) smd_sleep_exit(); /* Call CPR resume only for "idlePC" case */ if (msm_cpr_ops && from_idle) msm_cpr_ops->cpr_resume(); power_collapse_bail: if (cpu_is_msm8625()) { ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false); WARN_ON(ret); } return ret; }
static int omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) { struct omap3_processor_cx *cx; u8 cur_per_state, cur_neon_state, pre_neon_state, pre_per_state; struct timespec ts_preidle, ts_postidle, ts_idle; u32 fclken_core, iclken_core, fclken_per, iclken_per; u32 sdrcpwr_val, sdrc_power_register = 0x0; int wakeup_latency; int core_sleep_flg = 0; u32 per_ctx_saved = 0; int ret = -1; #ifdef CONFIG_ENABLE_SWLATENCY_MEASURE int idle_status = 0; #endif local_irq_disable(); local_fiq_disable(); if (need_resched()) { local_irq_enable(); local_fiq_enable(); return 0; } #ifdef CONFIG_ENABLE_SWLATENCY_MEASURE sw_latency_arr[swlat_arr_wrptr].sleep_start = omap_32k_sync_timer_read(); #endif PM_PREPWSTST_MPU = 0xFF; PM_PREPWSTST_CORE = 0xFF; PM_PREPWSTST_NEON = 0xFF; PM_PREPWSTST_PER = 0xFF; cx = cpuidle_get_statedata(state); target_state.mpu_state = cx->mpu_state; target_state.core_state = cx->core_state; /* take a time marker for residency */ getnstimeofday(&ts_preidle); if (cx->type == OMAP3_STATE_C0) { omap_sram_idle(); goto return_sleep_time; } if (cx->type > OMAP3_STATE_C1) sched_clock_idle_sleep_event(); /* about to enter deep idle */ correct_target_state(); wakeup_latency = cx->wakeup_latency; if (target_state.core_state != cx->core_state) { /* Currently, this can happen only for core_off */ /* Adjust wakeup latency to that of core_cswr state */ /* Hard coded now and needs to be made more generic */ /* omap3_power_states[4] is CSWR for core */ wakeup_latency = omap3_power_states[4].wakeup_latency; } /* Reprogram next wake up tick to adjust for wake latency */ if (wakeup_latency > 1000) { struct tick_device *d = tick_get_device(smp_processor_id()); ktime_t adjust, next, now = ktime_get(); if (ktime_to_ns(ktime_sub(d->evtdev->next_event, now)) > (wakeup_latency * 1000 + NSEC_PER_MSEC)) { adjust = ktime_set(0, (wakeup_latency * 1000)); next = ktime_sub(d->evtdev->next_event, adjust); clockevents_program_event(d->evtdev, next, now); } } /* Check for pending interrupts. If there is an interrupt, return */ if (INTCPS_PENDING_IRQ0 | INTCPS_PENDING_IRQ1 | INTCPS_PENDING_IRQ2) goto return_sleep_time; prcm_get_power_domain_state(DOM_PER, &cur_per_state); prcm_get_power_domain_state(DOM_NEON, &cur_neon_state); fclken_core = CM_FCLKEN1_CORE; iclken_core = CM_ICLKEN1_CORE; fclken_per = CM_FCLKEN_PER; iclken_per = CM_ICLKEN_PER; /* If target state if core_off, save registers * before changing anything */ if (target_state.core_state >= PRCM_CORE_OSWR_MEMRET) { prcm_save_registers(&target_state); omap_uart_save_ctx(0); omap_uart_save_ctx(1); } /* Check for pending interrupts. If there is an interrupt, return */ if (INTCPS_PENDING_IRQ0 | INTCPS_PENDING_IRQ1 | INTCPS_PENDING_IRQ2) goto return_sleep_time; /* Program MPU and NEON to target state */ if (target_state.mpu_state > PRCM_MPU_ACTIVE) { if ((cur_neon_state == PRCM_ON) && (target_state.neon_state != PRCM_ON)) { if (target_state.neon_state == PRCM_OFF) omap3_save_neon_context(); #ifdef CONFIG_HW_SUP_TRANS /* Facilitating SWSUP RET, from HWSUP mode */ prcm_set_clock_domain_state(DOM_NEON, PRCM_NO_AUTO, PRCM_FALSE); prcm_set_power_domain_state(DOM_NEON, PRCM_ON, PRCM_FORCE); #endif prcm_force_power_domain_state(DOM_NEON, target_state.neon_state); } #ifdef CONFIG_MPU_OFF /* Populate scrathpad restore address */ *(scratchpad_restore_addr) = restore_pointer_address; #endif if (target_state.core_state > PRCM_CORE_CSWR_MEMRET) { ret = omap3_save_secure_ram_context( target_state.core_state); if (ret) printk(KERN_ERR "omap3_save_secure_ram_context" "failed in idle %x\n", ret); if (core_off_notification != NULL) core_off_notification(PRCM_TRUE); } prcm_set_mpu_domain_state(target_state.mpu_state); } /* Check for pending interrupts. If there is an interrupt, return */ if (INTCPS_PENDING_IRQ0 | INTCPS_PENDING_IRQ1 | INTCPS_PENDING_IRQ2) goto restore; /* Program CORE and PER to target state */ if (target_state.core_state > PRCM_CORE_ACTIVE) { /* Log core sleep attmept */ core_sleep_flg = 1; #ifdef CONFIG_OMAP_SMARTREFLEX disable_smartreflex(SR1_ID); disable_smartreflex(SR2_ID); #endif /* Workaround for Silicon Errata 1.64 */ if (is_sil_rev_equal_to(OMAP3430_REV_ES1_0)) { if (CM_CLKOUT_CTRL & 0x80) CM_CLKOUT_CTRL &= ~(0x80); } prcm_set_core_domain_state(target_state.core_state); /* Enable Autoidle for GPT1 explicitly - Errata 1.4 */ CM_AUTOIDLE_WKUP |= 0x1; /* Disable UART-1,2 */ CM_FCLKEN1_CORE &= ~0x6000; /* Disable HSUSB OTG ICLK explicitly*/ CM_ICLKEN1_CORE &= ~0x10; /* Enabling IO_PAD capabilities */ PM_WKEN_WKUP |= 0x100; if (cur_per_state == PRCM_ON && cx->type >= OMAP3_STATE_C3 && !(CM_FCLKEN_PER & PER_FCLK_MASK)) { /* In ES3.1, Enable IO Daisy chain */ if (is_sil_rev_greater_than(OMAP3430_REV_ES3_0)) { PM_WKEN_WKUP |= 0x10000; /* Wait for daisy chain to be ready */ while ((PM_WKST_WKUP & 0x10000) == 0x0) ; /* clear the status */ PM_WKST_WKUP &= ~0x10000; } omap3_save_per_context(); prcm_set_power_domain_state(DOM_PER, PRCM_OFF, PRCM_AUTO); per_ctx_saved = 1; CM_FCLKEN_PER = 0; CM_ICLKEN_PER = 0; } } /* Check for pending interrupts. If there is an interrupt, return */ if (INTCPS_PENDING_IRQ0 | INTCPS_PENDING_IRQ1 | INTCPS_PENDING_IRQ2) goto restore; if (target_state.core_state == PRCM_CORE_OFF) { if (!is_device_type_gp() && is_sil_rev_greater_than(OMAP3430_REV_ES2_1)) { /* es3 series bug */ sdrc_power_register = sdrc_read_reg(SDRC_POWER); sdrcpwr_val = sdrc_power_register & ~(SDRC_PWR_AUTOCOUNT_MASK | SDRC_PWR_CLKCTRL_MASK); lock_scratchpad_sem(); sdrcpwr_val |= 0x120; save_to_scratchpad(SCRATHPAD_SDRCPWR_OFFSET, sdrcpwr_val); unlock_scratchpad_sem(); } } #ifdef CONFIG_ENABLE_SWLATENCY_MEASURE sw_latency_arr[swlat_arr_wrptr].sleep_end = omap_32k_sync_timer_read(); idle_status++; #endif omap_sram_idle(); if (target_state.core_state == PRCM_CORE_OFF) { if (!is_device_type_gp() && is_sil_rev_greater_than(OMAP3430_REV_ES2_1)) sdrc_write_reg(sdrc_power_register, SDRC_POWER); } restore: /* In case of ES3.1, disable IO daisy chain */ if (is_sil_rev_greater_than(OMAP3430_REV_ES3_0) && per_ctx_saved) PM_WKEN_WKUP &= ~(0x10000); /* Disabling IO_PAD capabilities */ if (core_sleep_flg) PM_WKEN_WKUP &= ~(0x100); /* Disabling IO_PAD capabilities */ PM_WKEN_WKUP &= ~(0x100); #ifdef OMAP3_START_RNG /*Capture the PM_PREPWSTST_CORE to be used later * for starting the RNG (Random Number Generator)*/ prepwst_core_rng = PM_PREPWSTST_CORE; #endif CM_FCLKEN1_CORE = fclken_core; CM_ICLKEN1_CORE = iclken_core; if (target_state.mpu_state > PRCM_MPU_ACTIVE) { #ifdef CONFIG_MPU_OFF /* On ES 2.0, if scrathpad is populated with valid * pointer, warm reset does not work * So populate scrathpad restore address only in * cpuidle and suspend calls */ *(scratchpad_restore_addr) = 0x0; #endif prcm_set_mpu_domain_state(PRCM_MPU_ACTIVE); if ((cur_neon_state == PRCM_ON) && (target_state.mpu_state > PRCM_MPU_INACTIVE)) { prcm_force_power_domain_state(DOM_NEON, cur_neon_state); prcm_get_pre_power_domain_state(DOM_NEON, &pre_neon_state); if (pre_neon_state == PRCM_OFF) omap3_restore_neon_context(); #ifdef CONFIG_HW_SUP_TRANS prcm_set_power_domain_state(DOM_NEON, PRCM_ON, PRCM_AUTO); #endif } } /* Continue core restoration part, only if Core-Sleep is attempted */ if ((target_state.core_state > PRCM_CORE_ACTIVE) && core_sleep_flg) { prcm_set_core_domain_state(PRCM_CORE_ACTIVE); #ifdef CONFIG_OMAP_SMARTREFLEX enable_smartreflex(SR1_ID); enable_smartreflex(SR2_ID); #endif if (target_state.core_state >= PRCM_CORE_OSWR_MEMRET) { #ifdef CONFIG_OMAP34XX_OFFMODE context_restore_update(DOM_CORE1); #endif prcm_restore_registers(&target_state); prcm_restore_core_context(target_state.core_state); omap3_restore_core_settings(); } /* Errata 1.4 * if the timer device gets idled which is when we * are cutting the timer ICLK which is when we try * to put Core to RET. * Wait Period = 2 timer interface clock cycles + * 1 timer functional clock cycle * Interface clock = L4 clock. For the computation L4 * clock is assumed at 50MHz (worst case). * Functional clock = 32KHz * Wait Period = 2*10^-6/50 + 1/32768 = 0.000030557 = 30.557uSec * Roundingoff the delay value to a safer 50uSec */ omap_udelay(GPTIMER_WAIT_DELAY); CM_AUTOIDLE_WKUP &= ~(0x1); if (core_off_notification != NULL) core_off_notification(PRCM_FALSE); } if (cur_per_state == PRCM_ON) { CM_FCLKEN_PER = fclken_per; CM_ICLKEN_PER = iclken_per; prcm_get_pre_power_domain_state(DOM_PER, &pre_per_state); if (pre_per_state == PRCM_OFF && per_ctx_saved) { if (enable_debug) per_off++; omap3_restore_per_context(); post_uart_inactivity(); #ifdef CONFIG_OMAP34XX_OFFMODE context_restore_update(DOM_PER); #endif } } pr_debug("MPU state:%x,CORE state:%x\n", PM_PREPWSTST_MPU, PM_PREPWSTST_CORE); store_prepwst(); return_sleep_time: getnstimeofday(&ts_postidle); ts_idle = timespec_sub(ts_postidle, ts_preidle); if (cx->type > OMAP3_STATE_C1) sched_clock_idle_wakeup_event(timespec_to_ns(&ts_idle)); #ifdef CONFIG_ENABLE_SWLATENCY_MEASURE if (idle_status) { sw_latency_arr[swlat_arr_wrptr].wkup_end = omap_32k_sync_timer_read(); sw_latency_arr[swlat_arr_wrptr].wkup_start = wakeup_start_32ksync; sw_latency_arr[swlat_arr_wrptr].cstate = ((PM_PREPWSTST_MPU & 0x3) << 2) | (PM_PREPWSTST_CORE & 0x3) | (omap_readl(0x48306CB0) << 16); swlat_arr_wrptr++; if (swlat_arr_wrptr == SW_LATENCY_ARR_SIZE) swlat_arr_wrptr = 0; } #endif local_irq_enable(); local_fiq_enable(); #ifdef OMAP3_START_RNG if (!is_device_type_gp()) { /*Start RNG after interrupts are enabled * and only when CORE OFF was successful */ if (!(prepwst_core_rng & 0x3)) { ret = omap3_start_rng(); if (ret) printk(KERN_INFO"Failed to generate new" " RN in idle %x\n", ret); prepwst_core_rng = 0xFF; } } #endif return (u32)timespec_to_ns(&ts_idle)/1000; }
static int rkpm_enter(suspend_state_t state) { //static u32 test_count=0; // printk(KERN_DEBUG"pm: "); printk("%s:\n",__FUNCTION__); //printk("pm test times=%d\n",++test_count); RKPM_DDR_FUN(prepare); rkpm_ctrbits_prepare(); // if(rkpm_chk_jdg_ctrbits(RKPM_CTR_RET_DIRT)) // return 0; rkpm_ddr_printch('0'); RKPM_BITCTR_DDR_FUN(PWR_DMNS,pwr_dmns); rkpm_ddr_printch('1'); local_fiq_disable(); RKPM_DDR_PFUN(save_setting,(rkpm_jdg_sram_ctrbits)); rkpm_ddr_printch('2'); RKPM_BITCTR_DDR_FUN(GTCLKS,gtclks); rkpm_ddr_printch('3'); RKPM_BITCTR_DDR_FUN(PLLS,plls); rkpm_ddr_printch('4'); RKPM_BITCTR_DDR_FUN(GPIOS,gpios); RKPM_DDR_FUN(regs_pread); rkpm_ddr_printch('5'); if(rkpm_chk_jdg_ctrbits(RKPM_CTRBITS_SOC_DLPMD)) { if(cpu_suspend(0,rk_lpmode_enter)==0) { RKPM_DDR_FUN(slp_re_first); rkpm_ddr_printch('D'); //rk_soc_pm_ctr_bits_prepare(); } rkpm_ddr_printch('d'); } else if(rkpm_chk_jdg_ctrbits(RKPM_CTR_IDLESRAM_MD)&&p_suspend_pie_cb) { call_with_stack(p_suspend_pie_cb,&rkpm_jdg_sram_ctrbits, rockchip_sram_stack); } else { dsb(); wfi(); } rkpm_ddr_printch('5'); RKPM_BITCTR_DDR_FUN(GPIOS,re_gpios); rkpm_ddr_printch('4'); RKPM_BITCTR_DDR_FUN(PLLS,re_plls); rkpm_ddr_printch('3'); RKPM_BITCTR_DDR_FUN(GTCLKS,re_gtclks); rkpm_ddr_printch('2'); RKPM_DDR_FUN(re_save_setting); local_fiq_enable(); rkpm_ddr_printch('1'); RKPM_BITCTR_DDR_FUN(PWR_DMNS,re_pwr_dmns); rkpm_ddr_printch('0'); rkpm_ddr_printch('\n'); RKPM_DDR_FUN(finish); return 0; }
/** * omap4_enter_idle - Programs OMAP4 to enter the specified state * @dev: cpuidle device * @state: The target state to be programmed * * Called from the CPUidle framework to program the device to the * specified low power state selected by the governor. * Returns the amount of time spent in the low power state. */ static int omap4_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) { struct omap4_processor_cx *cx = cpuidle_get_statedata(state); struct timespec ts_preidle, ts_postidle, ts_idle; u32 cpu1_state; int cpu_id = smp_processor_id(); /* Used to keep track of the total time in idle */ getnstimeofday(&ts_preidle); local_irq_disable(); local_fiq_disable(); /* * Do only WFI for non-boot CPU(aux cores) */ if (dev->cpu) { wmb(); DO_WFI(); goto return_sleep_time; } /* * Do only a WFI as long as CPU1 is online */ if (num_online_cpus() > 1) { wmb(); DO_WFI(); goto return_sleep_time; } /* * Hold on till CPU1 hits OFF */ cpu1_state = pwrdm_read_pwrst(cpu1_pd); if (cpu1_state != PWRDM_POWER_OFF) { wmb(); DO_WFI(); goto return_sleep_time; } if (cx->type > OMAP4_STATE_C1) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id); #ifdef CONFIG_PM_DEBUG pwrdm_pre_transition(); #endif pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state); omap4_set_pwrdm_state(mpu_pd, cx->mpu_state); pwrdm_set_logic_retst(core_pd, cx->core_logic_state); omap4_set_pwrdm_state(core_pd, cx->core_state); omap4_enter_sleep(dev->cpu, cx->cpu0_state); /* restore the MPU and CORE states to ON */ omap4_set_pwrdm_state(mpu_pd, PWRDM_POWER_ON); omap4_set_pwrdm_state(core_pd, PWRDM_POWER_ON); #ifdef CONFIG_PM_DEBUG pwrdm_post_transition(); #endif if (cx->type > OMAP4_STATE_C1) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); return_sleep_time: getnstimeofday(&ts_postidle); ts_idle = timespec_sub(ts_postidle, ts_preidle); local_irq_enable(); local_fiq_enable(); return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;; }
static int s3c_pm_enter(suspend_state_t state) { static unsigned long regs_save[16]; /* ensure the debug is initialised (if enabled) */ s3c_pm_debug_init(); S3C_PMDBG("%s(%d)\n", __func__, state); if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) { printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__); return -EINVAL; } /* check if we have anything to wake-up with... bad things seem * to happen if you suspend with no wakeup (system will often * require a full power-cycle) */ if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) && !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) { printk(KERN_ERR "%s: No wake-up sources!\n", __func__); printk(KERN_ERR "%s: Aborting sleep\n", __func__); return -EINVAL; } /* store the physical address of the register recovery block */ s3c_sleep_save_phys = virt_to_phys(regs_save); S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys); /* save all necessary core registers not covered by the drivers */ s3c_pm_save_gpios(); s3c_pm_save_uarts(); s3c_pm_save_core(); s3c_config_sleep_gpio(); /* set the irq configuration for wake */ s3c_pm_configure_extint(); S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx\n", s3c_irqwake_intmask, s3c_irqwake_eintmask); s3c_pm_arch_prepare_irqs(); /* call cpu specific preparation */ #if defined(CONFIG_WIMAX) || defined(CONFIG_WIMAX_MODULE) //cky 20101116 WiMAX ext-interrupt /* FIXME if (gpio_get_value(GPIO_WIMAX_EN)) { DBG("WIMAX POWER ON!! Set WIMAX_INT as Ext-Int.\n"); s3c_pm_set_eint(6, 0x0); // WIMAX_INT: GPH0(6); LOW LEVEL DETECT } */ #endif #ifdef FEATURE_FTM_SLEEP s3c_pm_check_auto_wakeup(); #endif pm_cpu_prep(); /* flush cache back to ram */ flush_cache_all(); s3c_pm_check_store(); /* clear wakeup_stat register for next wakeup reason */ __raw_writel(__raw_readl(S5P_WAKEUP_STAT), S5P_WAKEUP_STAT); /* send the cpu to sleep... */ s3c_pm_arch_stop_clocks(); /* s3c_cpu_save will also act as our return point from when * we resume as it saves its own register state and restores it * during the resume. */ pmstats->sleep_count++; pmstats->sleep_freq = __raw_readl(S5P_CLK_DIV0); s3c_cpu_save(regs_save); pmstats->wake_count++; pmstats->wake_freq = __raw_readl(S5P_CLK_DIV0); /* restore the cpu state using the kernel's cpu init code. */ cpu_init(); fiq_glue_resume(); local_fiq_enable(); s3c_pm_restore_core(); s3c_pm_restore_uarts(); s3c_pm_restore_gpios(); s5pv210_restore_eint_group(); s3c_pm_debug_init(); /* restore the system state */ if (pm_cpu_restore) pm_cpu_restore(); /* check what irq (if any) restored the system */ s3c_pm_arch_show_resume_irqs(); S3C_PMDBG("%s: post sleep, preparing to return\n", __func__); /* LEDs should now be 1110 */ s3c_pm_debug_smdkled(1 << 1, 0); #if defined(CONFIG_WIMAX) || defined(CONFIG_WIMAX_MODULE) //cky 20101116 ext-int for wimax /* FIXME if (gpio_get_value(GPIO_WIMAX_EN)) { DBG("WIMAX POWER ON!! Set WIMAX_INT: INPUT.\n"); s3c_pm_clear_eint(6); s3c_gpio_cfgpin(GPIO_WIMAX_INT, S3C_GPIO_INPUT); s3c_gpio_setpull(GPIO_WIMAX_INT, S3C_GPIO_PULL_UP); } */ #endif #ifdef FEATURE_FTM_SLEEP if (ftm_sleep == 1) { ftm_sleep = 0; pm_disable_rtctic(); wake_lock_timeout(&ftm_wake_lock, 11 * HZ); printk(KERN_DEBUG "pm_disable_rtctic...\n"); } #endif s3c_pm_check_restore(); /* ok, let's return from sleep */ S3C_PMDBG("S3C PM Resume (post-restore)\n"); return 0; }
/** * omap3_enter_idle - Programs OMAP3 to enter the specified state * @dev: cpuidle device * @state: The target state to be programmed * * Called from the CPUidle framework to program the device to the * specified target state selected by the governor. */ static int omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) { struct omap3_processor_cx *cx = cpuidle_get_statedata(state); struct timespec ts_preidle, ts_postidle, ts_idle; u32 core_next_state, per_next_state = 0, per_saved_state = 0; u32 mpu_state = cx->mpu_state, core_state = cx->core_state; current_cx_state = *cx; /* Used to keep track of the total time in idle */ getnstimeofday(&ts_preidle); local_irq_disable(); local_fiq_disable(); pwrdm_set_next_pwrst(mpu_pd, mpu_state); pwrdm_set_next_pwrst(core_pd, core_state); /* * Don't allow PER to go to OFF in idle state * transitions. * This is a tempory fix for display flashing issue * which occurs when off mode is enabled */ per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); if (per_next_state == PWRDM_POWER_OFF) per_next_state = PWRDM_POWER_RET; /* Are we changing PER target state? */ if (per_next_state != per_saved_state) pwrdm_set_next_pwrst(per_pd, per_next_state); if (omap_irq_pending() || need_resched()) goto return_sleep_time; if (cx->type == OMAP3_STATE_C1) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); } /* Execute ARM wfi */ omap_sram_idle(); if (cx->type == OMAP3_STATE_C1) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); } return_sleep_time: getnstimeofday(&ts_postidle); ts_idle = timespec_sub(ts_postidle, ts_preidle); /* Restore original PER state if it was modified */ if (per_next_state != per_saved_state) pwrdm_set_next_pwrst(per_pd, per_saved_state); local_irq_enable(); local_fiq_enable(); return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC; }
static void fiq_glue_syscore_resume(void) { fiq_glue_resume(); local_fiq_enable(); }
/** * omap3_enter_idle - Programs OMAP3 to enter the specified state * @dev: cpuidle device * @state: The target state to be programmed * * Called from the CPUidle framework to program the device to the * specified target state selected by the governor. */ static int omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) { struct omap3_processor_cx *cx = cpuidle_get_statedata(state); struct timespec ts_preidle, ts_postidle, ts_idle; u32 mpu_state, core_state; u8 idx; /* Used to keep track of the total time in idle */ getnstimeofday(&ts_preidle); /* * Check if the chosen idle state is valid. * If no, drop down to a lower valid state. * * (Expects the lowest idle state to be always VALID). */ if (!cx->valid) { for (idx = (cx->type - 1); idx > OMAP3_STATE_C1; idx--) { if (omap3_power_states[idx].valid) break; } state = &(dev->states[idx]); dev->last_state = state ; cx = cpuidle_get_statedata(state); } current_cx_state = *cx; mpu_state = cx->mpu_state; core_state = cx->core_state; local_irq_disable(); local_fiq_disable(); pwrdm_set_next_pwrst(mpu_pd, mpu_state); pwrdm_set_next_pwrst(core_pd, core_state); if (omap_irq_pending()) goto return_sleep_time; if (cx->type == OMAP3_STATE_C1) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); } /* Execute ARM wfi */ omap_sram_idle(); if (cx->type == OMAP3_STATE_C1) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); } return_sleep_time: getnstimeofday(&ts_postidle); ts_idle = timespec_sub(ts_postidle, ts_preidle); local_irq_enable(); local_fiq_enable(); return (u32)timespec_to_ns(&ts_idle)/1000; }
static int s3c_pm_enter(suspend_state_t state) { static unsigned long regs_save[16]; unsigned int gpio; /* ensure the debug is initialised (if enabled) */ s3c_pm_debug_init(); S3C_PMDBG("%s(%d)\n", __func__, state); if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) { printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__); return -EINVAL; } /* check if we have anything to wake-up with... bad things seem * to happen if you suspend with no wakeup (system will often * require a full power-cycle) */ if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) && !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) { printk(KERN_ERR "%s: No wake-up sources!\n", __func__); printk(KERN_ERR "%s: Aborting sleep\n", __func__); return -EINVAL; } /* store the physical address of the register recovery block */ s3c_sleep_save_phys = virt_to_phys(regs_save); S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys); /* save all necessary core registers not covered by the drivers */ #if 0 /* control power of moviNAND at PM and add 700ms delay for stabilization of moviNAND. */ gpio = readl(S5PV210_GPJ2DAT); writel(gpio & (~0x80), S5PV210_GPJ2DAT); mdelay(700); #endif s3c_pm_save_gpios(); s3c_pm_save_uarts(); s3c_pm_save_core(); config_sleep_gpio(); /* set the irq configuration for wake */ s3c_pm_configure_extint(); S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx\n", s3c_irqwake_intmask, s3c_irqwake_eintmask); s3c_pm_arch_prepare_irqs(); /* call cpu specific preparation */ pm_cpu_prep(); /* flush cache back to ram */ flush_cache_all(); s3c_pm_check_store(); /* clear wakeup_stat register for next wakeup reason */ __raw_writel(__raw_readl(S5P_WAKEUP_STAT), S5P_WAKEUP_STAT); /* send the cpu to sleep... */ s3c_pm_arch_stop_clocks(); /* s3c_cpu_save will also act as our return point from when * we resume as it saves its own register state and restores it * during the resume. */ pmstats->sleep_count++; pmstats->sleep_freq = __raw_readl(S5P_CLK_DIV0); s3c_cpu_save(regs_save); pmstats->wake_count++; pmstats->wake_freq = __raw_readl(S5P_CLK_DIV0); /* restore the cpu state using the kernel's cpu init code. */ cpu_init(); fiq_glue_resume(); local_fiq_enable(); s3c_pm_restore_core(); s3c_pm_restore_uarts(); s3c_pm_restore_gpios(); s5pv210_restore_eint_group(); s3c_pm_debug_init(); /* restore the system state */ if (pm_cpu_restore) pm_cpu_restore(); /* check what irq (if any) restored the system */ s3c_pm_arch_show_resume_irqs(); S3C_PMDBG("%s: post sleep, preparing to return\n", __func__); /* LEDs should now be 1110 */ s3c_pm_debug_smdkled(1 << 1, 0); s3c_pm_check_restore(); /* ok, let's return from sleep */ S3C_PMDBG("S3C PM Resume (post-restore)\n"); return 0; }
void notrace restore_processor_state(void) { local_fiq_enable(); }
/* * Let's power down on idle, but only if we are really * idle, because once we start down the path of * going idle we continue to do idle even if we get * a clock tick interrupt . . */ void omap_pm_idle(void) { extern __u32 arm_idlect1_mask; __u32 use_idlect1 = arm_idlect1_mask; int do_sleep = 0; local_irq_disable(); local_fiq_disable(); if (need_resched()) { local_fiq_enable(); local_irq_enable(); return; } /* * Since an interrupt may set up a timer, we don't want to * reprogram the hardware timer with interrupts enabled. * Re-enable interrupts only after returning from idle. */ timer_dyn_reprogram(); #ifdef CONFIG_OMAP_MPU_TIMER #warning Enable 32kHz OS timer in order to allow sleep states in idle use_idlect1 = use_idlect1 & ~(1 << 9); #else while (enable_dyn_sleep) { #ifdef CONFIG_CBUS_TAHVO_USB extern int vbus_active; /* Clock requirements? */ if (vbus_active) break; #endif do_sleep = 1; break; } #endif #ifdef CONFIG_OMAP_DM_TIMER use_idlect1 = omap_dm_timer_modify_idlect_mask(use_idlect1); #endif if (omap_dma_running()) use_idlect1 &= ~(1 << 6); /* We should be able to remove the do_sleep variable and multiple * tests above as soon as drivers, timer and DMA code have been fixed. * Even the sleep block count should become obsolete. */ if ((use_idlect1 != ~0) || !do_sleep) { __u32 saved_idlect1 = omap_readl(ARM_IDLECT1); if (cpu_is_omap15xx()) use_idlect1 &= OMAP1510_BIG_SLEEP_REQUEST; else use_idlect1 &= OMAP1610_IDLECT1_SLEEP_VAL; omap_writel(use_idlect1, ARM_IDLECT1); __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4"); omap_writel(saved_idlect1, ARM_IDLECT1); local_fiq_enable(); local_irq_enable(); return; }
*/ static int s3c_pm_enter(suspend_state_t state) { int tmp; static unsigned long regs_save[16]; /* ensure the debug is initialised (if enabled) */ s3c_pm_debug_init(); S3C_PMDBG("%s(%d)\n", __func__, state); if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) { printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__); return -EINVAL; } //Apollo + s5p_pad_pdn_control(); s3c_irqwake_intmask = 0xFFDF; // key //Apollo - /* check if we have anything to wake-up with... bad things seem * to happen if you suspend with no wakeup (system will often * require a full power-cycle) */ //printk("s3c_irqwake_intmask = 0x%08x, s3c_irqwake_intallow = 0x%08x+++++++\n", s3c_irqwake_intmask, s3c_irqwake_intallow); //printk("s3c_irqwake_eintmask = 0x%08x, s3c_irqwake_eintallow = 0x%08x+++++++\n", s3c_irqwake_eintmask, s3c_irqwake_eintallow); if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) && !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) { printk(KERN_ERR "%s: No wake-up sources!\n", __func__); printk(KERN_ERR "%s: Aborting sleep\n", __func__); return -EINVAL; } /* store the physical address of the register recovery block */ s3c_sleep_save_phys = virt_to_phys(regs_save); //Apollo + /* set flag for sleep mode idle2 flag is also reserved */ #define SLEEP_MODE 0 #define IDLE2_MODE 1 __raw_writel(SLEEP_MODE, S5P_INFORM1); //Apollo - S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys); /* save all necessary core registers not covered by the drivers */ s3c_pm_save_gpios(); s3c_pm_save_uarts(); s3c_pm_save_core(); //Apollo + s3c_config_sleep_gpio(); //ÅäÖÃÐÝÃßʱ¸÷io״̬ //Apollo - /* set the irq configuration for wake */ s3c_pm_configure_extint(); //printk(KERN_INFO"sleep: irq wakeup masks: %08lx,%08lx\n", s3c_irqwake_intmask, s3c_irqwake_eintmask); s3c_irqwake_intmask = 0xFFDF; s3c_pm_arch_prepare_irqs(); /* call cpu specific preparation */ pm_cpu_prep(); /* flush cache back to ram */ flush_cache_all(); s3c_pm_check_store(); /* clear wakeup_stat register for next wakeup reason */ __raw_writel(__raw_readl(S5P_WAKEUP_STAT), S5P_WAKEUP_STAT); /* send the cpu to sleep... */ s3c_pm_arch_stop_clocks(); /* s3c_cpu_save will also act as our return point from when * we resume as it saves its own register state and restores it * during the resume. */ pmstats->sleep_count++; pmstats->sleep_freq = __raw_readl(S5P_CLK_DIV0); s3c_cpu_save(regs_save); pmstats->wake_count++; pmstats->wake_freq = __raw_readl(S5P_CLK_DIV0); /* restore the cpu state using the kernel's cpu init code. */ cpu_init(); tmp = readl(S5P_WAKEUP_STAT); fiq_glue_resume(); local_fiq_enable(); s3c_pm_restore_core(); s3c_pm_restore_uarts(); s3c_pm_restore_gpios(); s5pv210_restore_eint_group(); s3c_pm_debug_init(); /* restore the system state */ if (pm_cpu_restore) pm_cpu_restore(); /* check what irq (if any) restored the system */ s3c_pm_arch_show_resume_irqs(); S3C_PMDBG("%s: post sleep, preparing to return\n", __func__); /* LEDs should now be 1110 */ // s3c_pm_debug_smdkled(1 << 1, 0); s3c_pm_check_restore(); /* ok, let's return from sleep */ S3C_PMDBG("S3C PM Resume (post-restore)\n");