Beispiel #1
0
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();
	}
}
Beispiel #2
0
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();
	}
}
Beispiel #3
0
/*!
 * @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;
}
Beispiel #4
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);
	}
}
Beispiel #7
0
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;
}
Beispiel #8
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;
}
Beispiel #10
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();
	}
}
Beispiel #11
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 (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);
	}
}
Beispiel #12
0
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;
}
Beispiel #13
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;
}
Beispiel #14
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);
	}
}
Beispiel #15
0
/*!
 * 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();
	}
}