예제 #1
0
파일: pmu.c 프로젝트: 1059232202/linux
static void exynos3250_pmu_init(void)
{
	unsigned int value;

	/*
	 * To prevent from issuing new bus request form L2 memory system
	 * If core status is power down, should be set '1' to L2 power down
	 */
	value = pmu_raw_readl(EXYNOS3_ARM_COMMON_OPTION);
	value |= EXYNOS3_OPTION_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
	pmu_raw_writel(value, EXYNOS3_ARM_COMMON_OPTION);

	/* Enable USE_STANDBY_WFI for all CORE */
	pmu_raw_writel(S5P_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);

	/*
	 * Set PSHOLD port for output high
	 */
	value = pmu_raw_readl(S5P_PS_HOLD_CONTROL);
	value |= S5P_PS_HOLD_OUTPUT_HIGH;
	pmu_raw_writel(value, S5P_PS_HOLD_CONTROL);

	/*
	 * Enable signal for PSHOLD port
	 */
	value = pmu_raw_readl(S5P_PS_HOLD_CONTROL);
	value |= S5P_PS_HOLD_EN;
	pmu_raw_writel(value, S5P_PS_HOLD_CONTROL);
}
예제 #2
0
static void exynos5_powerdown_conf(enum sys_powerdown mode)
{
	unsigned int i;
	unsigned int tmp;

	/*
	 * Enable both SC_FEEDBACK and SC_COUNTER
	 */
	for (i = 0; i < ARRAY_SIZE(exynos5_list_both_cnt_feed); i++) {
		tmp = pmu_raw_readl(exynos5_list_both_cnt_feed[i]);
		tmp |= (EXYNOS5_USE_SC_FEEDBACK |
			EXYNOS5_USE_SC_COUNTER);
		pmu_raw_writel(tmp, exynos5_list_both_cnt_feed[i]);
	}

	/*
	 * SKIP_DEACTIVATE_ACEACP_IN_PWDN_BITFIELD Enable
	 */
	tmp = pmu_raw_readl(EXYNOS5_ARM_COMMON_OPTION);
	tmp |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
	pmu_raw_writel(tmp, EXYNOS5_ARM_COMMON_OPTION);

	/*
	 * Disable WFI/WFE on XXX_OPTION
	 */
	for (i = 0; i < ARRAY_SIZE(exynos5_list_disable_wfi_wfe); i++) {
		tmp = pmu_raw_readl(exynos5_list_disable_wfi_wfe[i]);
		tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE |
			 EXYNOS5_OPTION_USE_STANDBYWFI);
		pmu_raw_writel(tmp, exynos5_list_disable_wfi_wfe[i]);
	}
}
예제 #3
0
파일: pmu.c 프로젝트: 1059232202/linux
void exynos_sys_powerdown_conf(enum sys_powerdown mode)
{
	unsigned int i;
	const struct exynos_pmu_data *pmu_data;

	if (!pmu_context)
		return;

	pmu_data = pmu_context->pmu_data;

	if (pmu_data->powerdown_conf)
		pmu_data->powerdown_conf(mode);

	if (pmu_data->pmu_config) {
		for (i = 0; (pmu_data->pmu_config[i].offset != PMU_TABLE_END); i++)
			pmu_raw_writel(pmu_data->pmu_config[i].val[mode],
					pmu_data->pmu_config[i].offset);
	}

	if (pmu_data->powerdown_conf_extra)
		pmu_data->powerdown_conf_extra(mode);

	if (pmu_data->pmu_config_extra) {
		for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++)
			pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode],
					pmu_data->pmu_config_extra[i].offset);
	}
}
예제 #4
0
static void exynos5250_pmu_init(void)
{
	unsigned int value;
	/*
	 * When SYS_WDTRESET is set, watchdog timer reset request
	 * is ignored by power management unit.
	 */
	value = pmu_raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
	value &= ~EXYNOS5_SYS_WDTRESET;
	pmu_raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);

	value = pmu_raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
	value &= ~EXYNOS5_SYS_WDTRESET;
	pmu_raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
}
예제 #5
0
파일: suspend.c 프로젝트: 3bsa/linux
static void exynos_pm_resume(void)
{
	u32 cpuid = read_cpuid_part();

	if (exynos_pm_central_resume())
		goto early_wakeup;

	/* For release retention */
	exynos_pm_release_retention();

	s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));

	if (cpuid == ARM_CPU_PART_CORTEX_A9)
		scu_enable(S5P_VA_SCU);

	if (call_firmware_op(resume) == -ENOSYS
	    && cpuid == ARM_CPU_PART_CORTEX_A9)
		exynos_cpu_restore_register();

early_wakeup:

	/* Clear SLEEP mode set in INFORM1 */
	pmu_raw_writel(0x0, S5P_INFORM1);
	exynos_set_delayed_reset_assertion(true);
}
예제 #6
0
파일: suspend.c 프로젝트: 3bsa/linux
static void exynos3250_pm_prepare(void)
{
	unsigned int tmp;

	/* Set wake-up mask registers */
	exynos_pm_set_wakeup_mask();

	tmp = pmu_raw_readl(EXYNOS3_ARM_L2_OPTION);
	tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
	pmu_raw_writel(tmp, EXYNOS3_ARM_L2_OPTION);

	exynos_pm_enter_sleep_mode();

	/* ensure at least INFORM0 has the resume address */
	pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
}
예제 #7
0
파일: suspend.c 프로젝트: 3bsa/linux
void __init exynos_pm_init(void)
{
	const struct of_device_id *match;
	struct device_node *np;
	u32 tmp;

	np = of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match);
	if (!np) {
		pr_err("Failed to find PMU node\n");
		return;
	}

	if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) {
		pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
		return;
	}

	pm_data = (const struct exynos_pm_data *) match->data;

	/* All wakeup disable */
	tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
	tmp |= pm_data->wake_disable_mask;
	pmu_raw_writel(tmp, S5P_WAKEUP_MASK);

	exynos_pm_syscore_ops.suspend	= pm_data->pm_suspend;
	exynos_pm_syscore_ops.resume	= pm_data->pm_resume;

	register_syscore_ops(&exynos_pm_syscore_ops);
	suspend_set_ops(&exynos_suspend_ops);
}
예제 #8
0
void __init exynos_pm_init(void)
{
	const struct of_device_id *match;
	u32 tmp;

	of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match);
	if (!match) {
		pr_err("Failed to find PMU node\n");
		return;
	}
	pm_data = (struct exynos_pm_data *) match->data;

	/* Platform-specific GIC callback */
	gic_arch_extn.irq_set_wake = exynos_irq_set_wake;

	/* All wakeup disable */
	tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
	tmp |= pm_data->wake_disable_mask;
	pmu_raw_writel(tmp, S5P_WAKEUP_MASK);

	exynos_pm_syscore_ops.suspend	= pm_data->pm_suspend;
	exynos_pm_syscore_ops.resume	= pm_data->pm_resume;

	register_syscore_ops(&exynos_pm_syscore_ops);
	suspend_set_ops(&exynos_suspend_ops);
}
예제 #9
0
파일: suspend.c 프로젝트: 3bsa/linux
static void exynos_pm_release_retention(void)
{
	unsigned int i;

	for (i = 0; (pm_data->release_ret_regs[i] != REG_TABLE_END); i++)
		pmu_raw_writel(EXYNOS_WAKEUP_FROM_LOWPWR,
				pm_data->release_ret_regs[i]);
}
예제 #10
0
파일: suspend.c 프로젝트: 3bsa/linux
static int exynos5420_pm_suspend(void)
{
	u32 this_cluster;

	exynos_pm_central_suspend();

	/* Setting SEQ_OPTION register */

	this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1);
	if (!this_cluster)
		pmu_raw_writel(EXYNOS5420_ARM_USE_STANDBY_WFI0,
				S5P_CENTRAL_SEQ_OPTION);
	else
		pmu_raw_writel(EXYNOS5420_KFC_USE_STANDBY_WFI0,
				S5P_CENTRAL_SEQ_OPTION);
	return 0;
}
예제 #11
0
파일: suspend.c 프로젝트: 3bsa/linux
static void exynos3250_pm_resume(void)
{
	u32 cpuid = read_cpuid_part();

	if (exynos_pm_central_resume())
		goto early_wakeup;

	/* For release retention */
	exynos_pm_release_retention();

	pmu_raw_writel(S5P_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);

	if (call_firmware_op(resume) == -ENOSYS
	    && cpuid == ARM_CPU_PART_CORTEX_A9)
		exynos_cpu_restore_register();

early_wakeup:

	/* Clear SLEEP mode set in INFORM1 */
	pmu_raw_writel(0x0, S5P_INFORM1);
}
예제 #12
0
파일: pmu.c 프로젝트: 1059232202/linux
static void exynos5420_powerdown_conf(enum sys_powerdown mode)
{
	u32 this_cluster;

	this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1);

	/*
	 * set the cluster id to IROM register to ensure that we wake
	 * up with the current cluster.
	 */
	pmu_raw_writel(this_cluster, EXYNOS_IROM_DATA2);
}
예제 #13
0
파일: suspend.c 프로젝트: sourcejedi/linux
static void exynos_pm_prepare(void)
{
    exynos_set_delayed_reset_assertion(false);

    /* Set wake-up mask registers */
    exynos_pm_set_wakeup_mask();

    exynos_pm_enter_sleep_mode();

    /* ensure at least INFORM0 has the resume address */
    pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
}
예제 #14
0
파일: pmu.c 프로젝트: 1059232202/linux
static void exynos3250_powerdown_conf_extra(enum sys_powerdown mode)
{
	unsigned int i;
	unsigned int tmp;

	/* Enable only SC_FEEDBACK */
	for (i = 0; i < ARRAY_SIZE(exynos3250_list_feed); i++) {
		tmp = pmu_raw_readl(exynos3250_list_feed[i]);
		tmp &= ~(EXYNOS3_OPTION_USE_SC_COUNTER);
		tmp |= EXYNOS3_OPTION_USE_SC_FEEDBACK;
		pmu_raw_writel(tmp, exynos3250_list_feed[i]);
	}

	if (mode != SYS_SLEEP)
		return;

	pmu_raw_writel(XUSBXTI_DURATION, EXYNOS3_XUSBXTI_DURATION);
	pmu_raw_writel(XXTI_DURATION, EXYNOS3_XXTI_DURATION);
	pmu_raw_writel(EXT_REGULATOR_DURATION, EXYNOS3_EXT_REGULATOR_DURATION);
	pmu_raw_writel(EXT_REGULATOR_COREBLK_DURATION,
		       EXYNOS3_EXT_REGULATOR_COREBLK_DURATION);
}
예제 #15
0
파일: suspend.c 프로젝트: 3bsa/linux
static int exynos_pm_suspend(void)
{
	exynos_pm_central_suspend();

	/* Setting SEQ_OPTION register */
	pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
		       S5P_CENTRAL_SEQ_OPTION);

	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
		exynos_cpu_save_register();

	return 0;
}
예제 #16
0
static void exynos5_power_off(void)
{
	unsigned int tmp;

	pr_info("Power down.\n");
	tmp = pmu_raw_readl(EXYNOS_PS_HOLD_CONTROL);
	tmp ^= (1 << 8);
	pmu_raw_writel(tmp, EXYNOS_PS_HOLD_CONTROL);

	/* Wait a little so we don't give a false warning below */
	mdelay(100);

	pr_err("Power down failed, please power off system manually.\n");
	while (1)
		;
}
예제 #17
0
static void exynos_pm_prepare(void)
{
	exynos_set_delayed_reset_assertion(false);

	/* Set wake-up mask registers */
	exynos_pm_set_wakeup_mask();

	s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));

	 if (pm_data->extra_save)
		s3c_pm_do_save(pm_data->extra_save,
				pm_data->num_extra_save);

	exynos_pm_enter_sleep_mode();

	/* ensure at least INFORM0 has the resume address */
	pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
}
예제 #18
0
파일: suspend.c 프로젝트: 3bsa/linux
static void exynos5420_pm_resume(void)
{
	unsigned long tmp;

	/* Restore the CPU0 low power state register */
	tmp = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG);
	pmu_raw_writel(tmp | S5P_CORE_LOCAL_PWR_EN,
		EXYNOS5_ARM_CORE0_SYS_PWR_REG);

	/* Restore the sysram cpu state register */
	__raw_writel(exynos5420_cpu_state,
		sysram_base_addr + EXYNOS5420_CPU_STATE);

	pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL,
			S5P_CENTRAL_SEQ_OPTION);

	if (exynos_pm_central_resume())
		goto early_wakeup;

	/* For release retention */
	exynos_pm_release_retention();

	pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3);

	s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));

early_wakeup:

	tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
	tmp &= ~EXYNOS5420_UFS;
	pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1);

	tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION);
	tmp &= ~EXYNOS5420_EMULATION;
	pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION);

	tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION);
	tmp &= ~EXYNOS5420_EMULATION;
	pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION);

	/* Clear SLEEP mode set in INFORM1 */
	pmu_raw_writel(0x0, S5P_INFORM1);
}
예제 #19
0
파일: suspend.c 프로젝트: 3bsa/linux
static void exynos5420_pm_prepare(void)
{
	unsigned int tmp;

	/* Set wake-up mask registers */
	exynos_pm_set_wakeup_mask();

	s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));

	exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3);
	/*
	 * The cpu state needs to be saved and restored so that the
	 * secondary CPUs will enter low power start. Though the U-Boot
	 * is setting the cpu state with low power flag, the kernel
	 * needs to restore it back in case, the primary cpu fails to
	 * suspend for any reason.
	 */
	exynos5420_cpu_state = __raw_readl(sysram_base_addr +
						EXYNOS5420_CPU_STATE);

	exynos_pm_enter_sleep_mode();

	/* ensure at least INFORM0 has the resume address */
	if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
		pmu_raw_writel(virt_to_phys(mcpm_entry_point), S5P_INFORM0);

	tmp = pmu_raw_readl(EXYNOS5_ARM_L2_OPTION);
	tmp &= ~EXYNOS5_USE_RETENTION;
	pmu_raw_writel(tmp, EXYNOS5_ARM_L2_OPTION);

	tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
	tmp |= EXYNOS5420_UFS;
	pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1);

	tmp = pmu_raw_readl(EXYNOS5420_ARM_COMMON_OPTION);
	tmp &= ~EXYNOS5420_L2RSTDISABLE_VALUE;
	pmu_raw_writel(tmp, EXYNOS5420_ARM_COMMON_OPTION);

	tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION);
	tmp |= EXYNOS5420_EMULATION;
	pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION);

	tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION);
	tmp |= EXYNOS5420_EMULATION;
	pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION);
}
예제 #20
0
파일: pmu.c 프로젝트: 1059232202/linux
static void exynos5420_pmu_init(void)
{
	unsigned int value;
	int i;

	/*
	 * Set the CMU_RESET, CMU_SYSCLK and CMU_CLKSTOP registers
	 * for local power blocks to Low initially as per Table 8-4:
	 * "System-Level Power-Down Configuration Registers".
	 */
	for (i = 0; i < ARRAY_SIZE(exynos5420_list_disable_pmu_reg); i++)
		pmu_raw_writel(0, exynos5420_list_disable_pmu_reg[i]);

	/* Enable USE_STANDBY_WFI for all CORE */
	pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);

	value  = pmu_raw_readl(EXYNOS_L2_OPTION(0));
	value &= ~EXYNOS5_USE_RETENTION;
	pmu_raw_writel(value, EXYNOS_L2_OPTION(0));

	value = pmu_raw_readl(EXYNOS_L2_OPTION(1));
	value &= ~EXYNOS5_USE_RETENTION;
	pmu_raw_writel(value, EXYNOS_L2_OPTION(1));

	/*
	 * If L2_COMMON is turned off, clocks related to ATB async
	 * bridge are gated. Thus, when ISP power is gated, LPI
	 * may get stuck.
	 */
	value = pmu_raw_readl(EXYNOS5420_LPI_MASK);
	value |= EXYNOS5420_ATB_ISP_ARM;
	pmu_raw_writel(value, EXYNOS5420_LPI_MASK);

	value  = pmu_raw_readl(EXYNOS5420_LPI_MASK1);
	value |= EXYNOS5420_ATB_KFC;
	pmu_raw_writel(value, EXYNOS5420_LPI_MASK1);

	/* Prevent issue of new bus request from L2 memory */
	value = pmu_raw_readl(EXYNOS5420_ARM_COMMON_OPTION);
	value |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
	pmu_raw_writel(value, EXYNOS5420_ARM_COMMON_OPTION);

	value = pmu_raw_readl(EXYNOS5420_KFC_COMMON_OPTION);
	value |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
	pmu_raw_writel(value, EXYNOS5420_KFC_COMMON_OPTION);

	/* This setting is to reduce suspend/resume time */
	pmu_raw_writel(DUR_WAIT_RESET, EXYNOS5420_LOGIC_RESET_DURATION3);

	/* Serialized CPU wakeup of Eagle */
	pmu_raw_writel(SPREAD_ENABLE, EXYNOS5420_ARM_INTR_SPREAD_ENABLE);

	pmu_raw_writel(SPREAD_USE_STANDWFI,
			EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI);

	pmu_raw_writel(0x1, EXYNOS5420_UP_SCHEDULER);
	pr_info("EXYNOS5420 PMU initialized\n");
}
예제 #21
0
/**
 * exynos_cluster_power_up : power up the specified cluster
 * @cluster : the cluster to power up
 */
void exynos_cluster_power_up(int cluster)
{
	pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
			EXYNOS_COMMON_CONFIGURATION(cluster));
}
예제 #22
0
/**
 * exynos_cluster_power_down : power down the specified cluster
 * @cluster : the cluster to power down
 */
void exynos_cluster_power_down(int cluster)
{
	pmu_raw_writel(0, EXYNOS_COMMON_CONFIGURATION(cluster));
}
예제 #23
0
/**
 * exynos_cpu_power_up : power up the specified cpu
 * @cpu : the cpu to power up
 *
 * Power up the specified cpu
 */
void exynos_cpu_power_up(int cpu)
{
	pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
			EXYNOS_ARM_CORE_CONFIGURATION(cpu));
}
예제 #24
0
/**
 * exynos_core_power_down : power down the specified cpu
 * @cpu : the cpu to power down
 *
 * Power down the specified cpu. The sequence must be finished by a
 * call to cpu_do_idle()
 *
 */
void exynos_cpu_power_down(int cpu)
{
	pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
}
예제 #25
0
파일: suspend.c 프로젝트: 3bsa/linux
static void exynos_pm_set_wakeup_mask(void)
{
	/* Set wake-up mask registers */
	pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
	pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
}
예제 #26
0
파일: suspend.c 프로젝트: 3bsa/linux
static void exynos_pm_enter_sleep_mode(void)
{
	/* Set value of power down register for sleep mode */
	exynos_sys_powerdown_conf(SYS_SLEEP);
	pmu_raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
}