void arch_idle(void) { if (enable_wait_mode) { mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); if (mem_clk_on_in_wait) { u32 reg; /* * MX6SL, MX6Q (TO1.2 or later) and * MX6DL (TO1.1 or later) have a bit in CCM_CGPR that * when cleared keeps the clocks to memories ON * when ARM is in WFI. This mode can be used when * IPG clock is very low (12MHz) and the ARM:IPG ratio * perhaps cannot be maintained. */ reg = __raw_readl(MXC_CCM_CGPR); reg &= ~MXC_CCM_CGPR_MEM_IPG_STOP_MASK; __raw_writel(reg, MXC_CCM_CGPR); ca9_do_idle(); } else if (num_possible_cpus() == 1) /* iMX6SL or iMX6DLS */ arch_idle_single_core(); else arch_idle_multi_core(); } else { mxc_cpu_lp_set(WAIT_CLOCKED); ca9_do_idle(); } }
void arch_idle(void) { int cpu = smp_processor_id(); if (enable_wait_mode) { #ifdef CONFIG_LOCAL_TIMERS if (!tick_broadcast_oneshot_active() || !tick_oneshot_mode_active()) return; clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); #endif if (enet_is_active) /* Don't allow the chip to enter WAIT mode if enet is active * and the GPIO workaround for ENET interrupts is not used, * since all ENET interrupts donot wake up the SOC. */ mxc_cpu_lp_set(WAIT_CLOCKED); else mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); if (mem_clk_on_in_wait) { u32 reg; /* * MX6SL, MX6Q (TO1.2 or later) and * MX6DL (TO1.1 or later) have a bit in * CCM_CGPR that when cleared keeps the * clocks to memories ON when ARM is in WFI. * This mode can be used when IPG clock is * very low (12MHz) and the ARM:IPG ratio * perhaps cannot be maintained. */ reg = __raw_readl(MXC_CCM_CGPR); reg &= ~MXC_CCM_CGPR_MEM_IPG_STOP_MASK; __raw_writel(reg, MXC_CCM_CGPR); ca9_do_idle(); } else if (num_possible_cpus() == 1) /* iMX6SL or iMX6DLS */ arch_idle_single_core(); else arch_idle_multi_core(cpu); #ifdef CONFIG_LOCAL_TIMERS clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); #endif } else { mxc_cpu_lp_set(WAIT_CLOCKED); ca9_do_idle(); } }
/*! * @file mach-mx35/pm.c * @brief This file contains suspend operations * * @ingroup MSL_MX35 */ static int mx35_suspend_enter(suspend_state_t state) { switch (state) { case PM_SUSPEND_MEM: mxc_cpu_lp_set(STOP_POWER_OFF); break; case PM_SUSPEND_STANDBY: mxc_cpu_lp_set(STOP_POWER_ON); break; default: return -EINVAL; } /* Executing CP15 (Wait-for-Interrupt) Instruction */ cpu_do_idle(); return 0; }
/*! * This function initializes the memory map. It is called during the * system startup to create static physical to virtual memory map for * the IO modules. */ void __init mx6_map_io(void) { iotable_init(mx6_io_desc, ARRAY_SIZE(mx6_io_desc)); mxc_iomux_v3_init(IO_ADDRESS(MX6Q_IOMUXC_BASE_ADDR)); mxc_arch_reset_init(IO_ADDRESS(MX6Q_WDOG1_BASE_ADDR)); mx6_set_cpu_type(); mxc_cpu_lp_set(WAIT_CLOCKED); }
/*! * This function puts the CPU into idle mode. It is called by default_idle() * in process.c file. */ void arch_idle(void) { /* * This should do all the clock switching * and wait for interrupt tricks. */ if (!mxc_jtag_enabled) { #ifdef CONFIG_MX35_DOZE_DURING_IDLE /*set as Doze mode */ mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); #else /* set as Wait mode */ mxc_cpu_lp_set(WAIT_UNCLOCKED); #endif cpu_do_idle(); } }
/*! * This function puts the CPU into idle mode. It is called by default_idle() * in process.c file. */ void arch_idle(void) { if (likely(!mxc_jtag_enabled)) { if (ddr_clk == NULL) ddr_clk = clk_get(NULL, "ddr_clk"); if (gpc_dvfs_clk == NULL) gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs_clk"); /* gpc clock is needed for SRPG */ clk_enable(gpc_dvfs_clk); mxc_cpu_lp_set(arch_idle_mode); if (cpu_is_mx50() && (clk_get_usecount(ddr_clk) == 0)) { memcpy(wait_in_iram_base, mx50_wait, SZ_4K); wait_in_iram = (void *)wait_in_iram_base; if (low_bus_freq_mode) { u32 reg, cpu_podf; reg = __raw_readl(apll_base + 0x50); reg = 0x120490; __raw_writel(reg, apll_base + 0x50); reg = __raw_readl(apll_base + 0x80); reg |= 1; __raw_writel(reg, apll_base + 0x80); /* Move ARM to be sourced from 24MHz XTAL. * when ARM is in WFI. */ if (pll1_sw_clk == NULL) pll1_sw_clk = clk_get(NULL, "pll1_sw_clk"); if (osc == NULL) osc = clk_get(NULL, "lp_apm"); if (pll1_main_clk == NULL) pll1_main_clk = clk_get(NULL, "pll1_main_clk"); clk_set_parent(pll1_sw_clk, osc); /* Set the ARM-PODF divider to 1. */ cpu_podf = __raw_readl(MXC_CCM_CACRR); __raw_writel(0x01, MXC_CCM_CACRR); wait_in_iram(ccm_base, databahn_base); /* Set the ARM-POD divider back * to the original. */ __raw_writel(cpu_podf, MXC_CCM_CACRR); clk_set_parent(pll1_sw_clk, pll1_main_clk); } else wait_in_iram(ccm_base, databahn_base); } else cpu_do_idle(); clk_disable(gpc_dvfs_clk); clk_put(ddr_clk); } }
static int mx37_suspend_enter(suspend_state_t state) { if (tzic_enable_wake(0) != 0) return -EAGAIN; switch (state) { case PM_SUSPEND_MEM: mxc_cpu_lp_set(STOP_POWER_OFF); break; case PM_SUSPEND_STANDBY: mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); break; default: return -EINVAL; } cpu_do_idle(); return 0; }
void arch_idle(void) { if (enable_wait_mode) { if ((num_online_cpus() == num_present_cpus()) && mx6_wait_in_iram != NULL) { mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); mx6_wait_in_iram(MXC_CCM_BASE); } } else cpu_do_idle(); }
static int mx51_suspend_enter(suspend_state_t state) { if (gpc_dvfs_clk == NULL) gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs_clk"); /* gpc clock is needed for SRPG */ clk_enable(gpc_dvfs_clk); switch (state) { case PM_SUSPEND_MEM: mxc_cpu_lp_set(STOP_POWER_OFF); break; case PM_SUSPEND_STANDBY: mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); break; default: return -EINVAL; } if (tzic_enable_wake(0) != 0) return -EAGAIN; if (state == PM_SUSPEND_MEM) { cpu_do_suspend_workaround(); /*clear the EMPGC0/1 bits */ __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR); __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR); } else { if ((mxc_cpu_is_rev(CHIP_REV_2_0)) < 0) { /* do cpu_idle_workaround */ u32 l2_iram_addr = IDLE_IRAM_BASE_ADDR; if (!iram_ready) return 0; if (l2_iram_addr > 0x1FFE8000) cpu_cortexa8_do_idle(IO_ADDRESS(l2_iram_addr)); } else { cpu_do_idle(); } } clk_disable(gpc_dvfs_clk); return 0; }
/*! * This function puts the CPU into idle mode. It is called by default_idle() * in process.c file. */ void arch_idle(void) { /* * This should do all the clock switching * and wait for interrupt tricks. */ if (!mxc_jtag_enabled) { /* set as Wait mode */ mxc_cpu_lp_set(WAIT_UNCLOCKED); cpu_do_idle(); } }
/*! * This function puts the CPU into idle mode. It is called by default_idle() * in process.c file. */ void arch_idle(void) { if (likely(!mxc_jtag_enabled)) { if (gpc_dvfs_clk == NULL) gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs_clk"); /* gpc clock is needed for SRPG */ clk_enable(gpc_dvfs_clk); mxc_cpu_lp_set(arch_idle_mode); if ((mxc_cpu_is_rev(CHIP_REV_2_0)) < 0) { u32 l2_iram_addr = IDLE_IRAM_BASE_ADDR; if (!iram_ready) return; if (l2_iram_addr > 0x1FFE8000) cpu_cortexa8_do_idle(IO_ADDRESS(l2_iram_addr)); } else { cpu_do_idle(); } clk_disable(gpc_dvfs_clk); } }
static int mx6_suspend_enter(suspend_state_t state) { unsigned int wake_irq_isr[4]; unsigned int cpu_type; struct gic_dist_state gds; struct gic_cpu_state gcs; bool arm_pg = false; if (cpu_is_mx6q()) cpu_type = MXC_CPU_MX6Q; else if (cpu_is_mx6dl()) cpu_type = MXC_CPU_MX6DL; else cpu_type = MXC_CPU_MX6SL; wake_irq_isr[0] = __raw_readl(gpc_base + GPC_ISR1_OFFSET) & gpc_wake_irq[0]; wake_irq_isr[1] = __raw_readl(gpc_base + GPC_ISR2_OFFSET) & gpc_wake_irq[1]; wake_irq_isr[2] = __raw_readl(gpc_base + GPC_ISR3_OFFSET) & gpc_wake_irq[2]; wake_irq_isr[3] = __raw_readl(gpc_base + GPC_ISR4_OFFSET) & gpc_wake_irq[3]; if (wake_irq_isr[0] | wake_irq_isr[1] | wake_irq_isr[2] | wake_irq_isr[3]) { printk(KERN_INFO "There are wakeup irq pending,system resume!\n"); printk(KERN_INFO "wake_irq_isr[0-3]: 0x%x, 0x%x, 0x%x, 0x%x\n", wake_irq_isr[0], wake_irq_isr[1], wake_irq_isr[2], wake_irq_isr[3]); return 0; } mx6_suspend_store(); /* * i.MX6dl TO1.0/i.MX6dq TO1.1/1.0 TKT094231: can't support * ARM_POWER_OFF mode. */ if (state == PM_SUSPEND_MEM && ((mx6dl_revision() == IMX_CHIP_REVISION_1_0) || (cpu_is_mx6q() && mx6q_revision() <= IMX_CHIP_REVISION_1_1))) { state = PM_SUSPEND_STANDBY; } switch (state) { case PM_SUSPEND_MEM: disp_power_down(); usb_power_down_handler(); mxc_cpu_lp_set(ARM_POWER_OFF); arm_pg = true; break; case PM_SUSPEND_STANDBY: if (cpu_is_mx6sl()) { disp_power_down(); usb_power_down_handler(); mxc_cpu_lp_set(STOP_XTAL_ON); arm_pg = true; } else mxc_cpu_lp_set(STOP_POWER_OFF); break; default: return -EINVAL; } /* * L2 can exit by 'reset' or Inband beacon (from remote EP) * toggling phy_powerdown has same effect as 'inband beacon' * So, toggle bit18 of GPR1, to fix errata * "PCIe PCIe does not support L2 Power Down" */ __raw_writel(__raw_readl(IOMUXC_GPR1) | (1 << 18), IOMUXC_GPR1); if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY) { local_flush_tlb_all(); flush_cache_all(); if (arm_pg) { /* preserve gic state */ save_gic_dist_state(0, &gds); save_gic_cpu_state(0, &gcs); } if (pm_data && pm_data->suspend_enter) pm_data->suspend_enter(); suspend_in_iram(state, (unsigned long)iram_paddr, (unsigned long)suspend_iram_base, cpu_type); if (pm_data && pm_data->suspend_exit) pm_data->suspend_exit(); /* Reset the RBC counter. */ /* All interrupts should be masked before the * RBC counter is reset. */ /* Mask all interrupts. These will be unmasked by * the mx6_suspend_restore routine below. */ __raw_writel(0xffffffff, gpc_base + 0x08); __raw_writel(0xffffffff, gpc_base + 0x0c); __raw_writel(0xffffffff, gpc_base + 0x10); __raw_writel(0xffffffff, gpc_base + 0x14); /* Clear the RBC counter and RBC_EN bit. */ /* Disable the REG_BYPASS_COUNTER. */ __raw_writel(__raw_readl(MXC_CCM_CCR) & ~MXC_CCM_CCR_RBC_EN, MXC_CCM_CCR); /* Make sure we clear REG_BYPASS_COUNT*/ __raw_writel(__raw_readl(MXC_CCM_CCR) & (~MXC_CCM_CCR_REG_BYPASS_CNT_MASK), MXC_CCM_CCR); /* Need to wait for a minimum of 2 CLKILS (32KHz) for the * counter to clear and reset. */ udelay(80); if (arm_pg) { /* restore gic registers */ restore_gic_dist_state(0, &gds); restore_gic_cpu_state(0, &gcs); } if (state == PM_SUSPEND_MEM || (cpu_is_mx6sl())) { usb_power_up_handler(); disp_power_up(); } mx6_suspend_restore(); __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base + HW_ANADIG_ANA_MISC0_CLR); } else { cpu_do_idle(); } /* * L2 can exit by 'reset' or Inband beacon (from remote EP) * toggling phy_powerdown has same effect as 'inband beacon' * So, toggle bit18 of GPR1, to fix errata * "PCIe PCIe does not support L2 Power Down" */ __raw_writel(__raw_readl(IOMUXC_GPR1) & (~(1 << 18)), IOMUXC_GPR1); return 0; }
static int mx6_suspend_enter(suspend_state_t state) { unsigned int wake_irq_isr[4]; struct gic_dist_state gds; struct gic_cpu_state gcs; wake_irq_isr[0] = __raw_readl(gpc_base + GPC_ISR1_OFFSET) & gpc_wake_irq[0]; wake_irq_isr[1] = __raw_readl(gpc_base + GPC_ISR2_OFFSET) & gpc_wake_irq[1]; wake_irq_isr[2] = __raw_readl(gpc_base + GPC_ISR3_OFFSET) & gpc_wake_irq[2]; wake_irq_isr[3] = __raw_readl(gpc_base + GPC_ISR4_OFFSET) & gpc_wake_irq[3]; if (wake_irq_isr[0] | wake_irq_isr[1] | wake_irq_isr[2] | wake_irq_isr[3]) { printk(KERN_INFO "There are wakeup irq pending,system resume!\n"); printk(KERN_INFO "wake_irq_isr[0-3]: 0x%x, 0x%x, 0x%x, 0x%x\n", wake_irq_isr[0], wake_irq_isr[1], wake_irq_isr[2], wake_irq_isr[3]); return 0; } mx6_suspend_store(); /* i.MX6dl TO1.0 TKT094231: can't support ARM_POWER_OFF mode */ if (state == PM_SUSPEND_MEM && cpu_is_mx6dl()) state = PM_SUSPEND_STANDBY; switch (state) { case PM_SUSPEND_MEM: gpu_power_down(); usb_power_down_handler(); mxc_cpu_lp_set(ARM_POWER_OFF); break; case PM_SUSPEND_STANDBY: mxc_cpu_lp_set(STOP_POWER_OFF); break; default: return -EINVAL; } if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY) { if (pm_data && pm_data->suspend_enter) pm_data->suspend_enter(); local_flush_tlb_all(); flush_cache_all(); if (state == PM_SUSPEND_MEM) { /* preserve gic state */ save_gic_dist_state(0, &gds); save_gic_cpu_state(0, &gcs); } suspend_in_iram(state, (unsigned long)iram_paddr, (unsigned long)suspend_iram_base); if (state == PM_SUSPEND_MEM) { /* restore gic registers */ restore_gic_dist_state(0, &gds); restore_gic_cpu_state(0, &gcs); usb_power_up_handler(); gpu_power_up(); } mx6_suspend_restore(); if (pm_data && pm_data->suspend_exit) pm_data->suspend_exit(); } else { cpu_do_idle(); } return 0; }
/*! * This function puts the CPU into idle mode. It is called by default_idle() * in process.c file. */ void arch_idle(void) { if (likely(!mxc_jtag_enabled)) { if (ddr_clk == NULL) ddr_clk = clk_get(NULL, "ddr_clk"); if (gpc_dvfs_clk == NULL) gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs_clk"); /* gpc clock is needed for SRPG */ clk_enable(gpc_dvfs_clk); mxc_cpu_lp_set(arch_idle_mode); if (cpu_is_mx50() && (clk_get_usecount(ddr_clk) == 0)) { if (sys_clk == NULL) sys_clk = clk_get(NULL, "sys_clk"); if (low_bus_freq_mode) { u32 reg, cpu_podf; reg = __raw_readl(apll_base + 0x50); reg = 0x120490; __raw_writel(reg, apll_base + 0x50); reg = __raw_readl(apll_base + 0x80); reg |= 1; __raw_writel(reg, apll_base + 0x80); if (mx50_ddr_type != MX50_DDR2) { /* Move ARM to be sourced from 24MHz XTAL. * when ARM is in WFI. */ if (pll1_sw_clk == NULL) pll1_sw_clk = clk_get(NULL, "pll1_sw_clk"); if (osc == NULL) osc = clk_get(NULL, "lp_apm"); if (pll1_main_clk == NULL) pll1_main_clk = clk_get(NULL, "pll1_main_clk"); clk_set_parent(pll1_sw_clk, osc); /* Set the ARM-PODF divider to 1. */ cpu_podf = __raw_readl(MXC_CCM_CACRR); __raw_writel(0x01, MXC_CCM_CACRR); while (__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_ARM_PODF_BUSY) ; } wait_in_iram(ccm_base, databahn_base, clk_get_usecount(sys_clk)); if (mx50_ddr_type != MX50_DDR2) { /* Set the ARM-POD divider back * to the original. */ __raw_writel(cpu_podf, MXC_CCM_CACRR); while (__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_ARM_PODF_BUSY) ; clk_set_parent(pll1_sw_clk, pll1_main_clk); } } else wait_in_iram(ccm_base, databahn_base, clk_get_usecount(sys_clk)); } else if (cpu_is_mx53() && (clk_get_usecount(ddr_clk) == 0) && low_bus_freq_mode) { suspend_in_iram(suspend_param1, NULL, NULL); } else cpu_do_idle(); clk_disable(gpc_dvfs_clk); clk_put(ddr_clk); } }
/*! * This function puts the CPU into idle mode. It is called by default_idle() * in process.c file. */ void arch_idle(void) { int emi_gated_off = 0, peri_pll_gated = 0; int usb_hc1_gated_off = 0; if (mxc_jtag_enabled) return; /* * This should do all the clock switching * and wait for interrupt tricks. */ if (!mx35_luigi_audio_playing_flag && !doze_lpm_flag) { if (clks_initialized == 0) { clks_initialized = 1; initialize_clocks(); disable_clks_for_good(); pmcr2_disable_oscaudio(); reduce_nfc_clk_speed(); } local_fiq_disable(); disable_cgr_clks(); if (eink_doze_counter()) cko1_disable(); clk_disable(ipu_clk); if (check_wan_status()) usb_hc1_gated_off = 1; else { if (usb_hc1_gated) usb_hc1_gated_off = 1; } /* * Check if emi_clk can be gated */ if ((!sdma_clk->usecount) && (ipu_clk->usecount <= 1) && (usb_hc1_gated_off == 1) && (usb_otg_gated_off == 1) && (nfc_clk->usecount == 0) // && (sd_turn_of_dma == 0) && (fec_clk->usecount == 0) ) { emi_gated_off = 1; clk_disable(emi_clk); } /* * Check if the peri_pll_clk can be gated */ if (!check_sdhc_clk() && (emi_gated_off == 1) && (!usb_ahb_clk->usecount) && (!uart_clk->usecount)) { peri_pll_disable(); peri_pll_gated = 1; } mxc_cpu_lp_set(WAIT_UNCLOCKED); cpu_do_idle(); if (peri_pll_gated == 1) peri_pll_enable(); if (emi_gated_off == 1) { clk_enable(emi_clk); } clk_enable(ipu_clk); cko1_enable(); enable_cgr_clks(); local_fiq_enable(); } else { mxc_cpu_lp_set(WAIT_UNCLOCKED); cpu_do_idle(); enable_cgr_clks(); } }