Exemple #1
0
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);
}
Exemple #2
0
void __init exynos_firmware_init(void)
{
	struct device_node *nd;
	const __be32 *addr;

	nd = of_find_compatible_node(NULL, NULL,
					"samsung,secure-firmware");
	if (!nd)
		return;

	addr = of_get_address(nd, 0, NULL, NULL);
	if (!addr) {
		pr_err("%s: No address specified.\n", __func__);
		return;
	}

	pr_info("Running under secure firmware.\n");

	register_firmware_ops(&exynos_firmware_ops);

	/*
	 * Exynos 4 SoCs (based on Cortex A9 and equipped with L2C-310),
	 * running under secure firmware, require certain registers of L2
	 * cache controller to be written in secure mode. Here .write_sec
	 * callback is provided to perform necessary SMC calls.
	 */
	if (IS_ENABLED(CONFIG_CACHE_L2X0) &&
	    read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
		outer_cache.write_sec = exynos_l2_write_sec;
		outer_cache.configure = exynos_l2_configure;
	}
}
Exemple #3
0
static int exynos_suspend(void)
{
	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
		exynos_save_cp15();

	writel(EXYNOS_SLEEP_MAGIC, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
	writel(virt_to_phys(exynos_cpu_resume_ns),
		sysram_ns_base_addr + EXYNOS_BOOT_ADDR);

	return cpu_suspend(0, exynos_cpu_suspend);
}
Exemple #4
0
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;
}
Exemple #5
0
/*
 * CPU PMU identification and probing.
 */
static int probe_current_pmu(struct arm_pmu *pmu)
{
	int cpu = get_cpu();
	int ret = -ENODEV;

	pr_info("probing PMU on CPU %d\n", cpu);

	switch (read_cpuid_part()) {
	/* ARM Ltd CPUs. */
	case ARM_CPU_PART_ARM1136:
		ret = armv6_1136_pmu_init(pmu);
		break;
	case ARM_CPU_PART_ARM1156:
		ret = armv6_1156_pmu_init(pmu);
		break;
	case ARM_CPU_PART_ARM1176:
		ret = armv6_1176_pmu_init(pmu);
		break;
	case ARM_CPU_PART_ARM11MPCORE:
		ret = armv6mpcore_pmu_init(pmu);
		break;
	case ARM_CPU_PART_CORTEX_A8:
		ret = armv7_a8_pmu_init(pmu);
		break;
	case ARM_CPU_PART_CORTEX_A9:
		ret = armv7_a9_pmu_init(pmu);
		break;

	default:
		if (read_cpuid_implementor() == ARM_CPU_IMP_INTEL) {
			switch (xscale_cpu_arch_version()) {
			case ARM_CPU_XSCALE_ARCH_V1:
				ret = xscale1pmu_init(pmu);
				break;
			case ARM_CPU_XSCALE_ARCH_V2:
				ret = xscale2pmu_init(pmu);
				break;
			}
		}
		break;
	}

	put_cpu();
	return ret;
}
Exemple #6
0
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);
}
Exemple #7
0
static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
{
	int i;

	exynos_sysram_init();

	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
		scu_enable(scu_base_addr());

	/*
	 * Write the address of secondary startup into the
	 * system-wide flags register. The boot monitor waits
	 * until it receives a soft interrupt, and then the
	 * secondary CPU branches to this address.
	 *
	 * Try using firmware operation first and fall back to
	 * boot register if it fails.
	 */
	for (i = 1; i < max_cpus; ++i) {
		unsigned long boot_addr;
		u32 mpidr;
		u32 core_id;
		int ret;

		mpidr = cpu_logical_map(i);
		core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
		boot_addr = virt_to_phys(exynos4_secondary_startup);

		ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr);
		if (ret && ret != -ENOSYS)
			break;
		if (ret == -ENOSYS) {
			void __iomem *boot_reg = cpu_boot_reg(core_id);

			if (IS_ERR(boot_reg))
				break;
			__raw_writel(boot_addr, cpu_boot_reg(core_id));
		}
	}
}
Exemple #8
0
static int exynos_do_idle(unsigned long mode)
{
	switch (mode) {
	case FW_DO_IDLE_AFTR:
		if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
			exynos_save_cp15();
		__raw_writel(virt_to_phys(exynos_cpu_resume_ns),
			     sysram_ns_base_addr + 0x24);
		__raw_writel(EXYNOS_AFTR_MAGIC, sysram_ns_base_addr + 0x20);
		if (soc_is_exynos3250()) {
			exynos_smc(SMC_CMD_SAVE, OP_TYPE_CORE,
				   SMC_POWERSTATE_IDLE, 0);
			exynos_smc(SMC_CMD_SHUTDOWN, OP_TYPE_CLUSTER,
				   SMC_POWERSTATE_IDLE, 0);
		} else
			exynos_smc(SMC_CMD_CPU0AFTR, 0, 0, 0);
		break;
	case FW_DO_IDLE_SLEEP:
		exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
	}
	return 0;
}
Exemple #9
0
static void __init exynos_smp_init_cpus(void)
{
	void __iomem *scu_base = scu_base_addr();
	unsigned int i, ncores;

	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
		ncores = scu_base ? scu_get_core_count(scu_base) : 1;
	else
		/*
		 * CPU Nodes are passed thru DT and set_cpu_possible
		 * is set by "arm_dt_init_cpu_maps".
		 */
		return;

	/* sanity check */
	if (ncores > nr_cpu_ids) {
		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
			ncores, nr_cpu_ids);
		ncores = nr_cpu_ids;
	}

	for (i = 0; i < ncores; i++)
		set_cpu_possible(i, true);
}
Exemple #10
0
static int __init rockchip_ca9_cpuidle_init(void)
{
	struct device_node *np;
	int ret;

	if (!cpu_is_rockchip())
		return -ENODEV;
	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9)
		return -ENODEV;
	np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic");
	if (!np)
		return -ENODEV;
	gic_cpu_base = of_iomap(np, 1);
	if (!gic_cpu_base) {
		pr_err("%s: failed to map gic cpu registers\n", __func__);
		return -EINVAL;
	}
	rockchip_ca9_cpuidle_driver.states[0].enter = rockchip_ca9_cpuidle_enter;
	ret = cpuidle_register(&rockchip_ca9_cpuidle_driver, NULL);
	if (ret)
		pr_err("%s: failed to register cpuidle driver: %d\n", __func__, ret);

	return ret;
}
Exemple #11
0
static void __init global_timer_of_register(struct device_node *np)
{
    struct clk *gt_clk;
    int err = 0;

    /*
     * In A9 r2p0 the comparators for each processor with the global timer
     * fire when the timer value is greater than or equal to. In previous
     * revisions the comparators fired when the timer value was equal to.
     */
    if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9
            && (read_cpuid_id() & 0xf0000f) < 0x200000) {
        pr_warn("global-timer: non support for this cpu version.\n");
        return;
    }

    gt_ppi = irq_of_parse_and_map(np, 0);
    if (!gt_ppi) {
        pr_warn("global-timer: unable to parse irq\n");
        return;
    }

    gt_base = of_iomap(np, 0);
    if (!gt_base) {
        pr_warn("global-timer: invalid base address\n");
        return;
    }

    gt_clk = of_clk_get(np, 0);
    if (!IS_ERR(gt_clk)) {
        err = clk_prepare_enable(gt_clk);
        if (err)
            goto out_unmap;
    } else {
        pr_warn("global-timer: clk not found\n");
        err = -EINVAL;
        goto out_unmap;
    }

    gt_clk_rate = clk_get_rate(gt_clk);
    gt_evt = alloc_percpu(struct clock_event_device);
    if (!gt_evt) {
        pr_warn("global-timer: can't allocate memory\n");
        err = -ENOMEM;
        goto out_clk;
    }

    err = request_percpu_irq(gt_ppi, gt_clockevent_interrupt,
                             "gt", gt_evt);
    if (err) {
        pr_warn("global-timer: can't register interrupt %d (%d)\n",
                gt_ppi, err);
        goto out_free;
    }

    err = register_cpu_notifier(&gt_cpu_nb);
    if (err) {
        pr_warn("global-timer: unable to register cpu notifier.\n");
        goto out_irq;
    }

    /* Immediately configure the timer on the boot CPU */
    gt_clocksource_init();
    gt_clockevents_init(this_cpu_ptr(gt_evt));

    return;

out_irq:
    free_percpu_irq(gt_ppi, gt_evt);
out_free:
    free_percpu(gt_evt);
out_clk:
    clk_disable_unprepare(gt_clk);
out_unmap:
    iounmap(gt_base);
    WARN(err, "ARM Global timer register failed (%d)\n", err);
}