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); call_firmware_op(prepare_idle); /* Do suspend by ourselves if the firmware does not implement it */ if (call_firmware_op(do_idle) == -ENOSYS) 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 void __init exynos_smp_prepare_cpus(unsigned int max_cpus) { int i; if (read_cpuid_part_number() == 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 phys_cpu; unsigned long boot_addr; phys_cpu = cpu_logical_map(i); boot_addr = virt_to_phys(exynos4_secondary_startup); if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr)) __raw_writel(boot_addr, cpu_boot_reg(phys_cpu)); } }
void show_pm_secure_mem_status(void) { int i = 1; int val = 0; #ifndef CONFIG_SUNXI_TRUSTZONE while(i < STANDBY_STATUS_REG_NUM) { pm_secure_status_reg_tmp.bits.reg_sel = i; if (!hwspin_lock_timeout(MEM_RTC_REG_HWSPINLOCK, 20000)) { (*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval; pm_secure_status_reg_tmp.dwval = (*pm_secure_status_reg).dwval; hwspin_unlock(MEM_RTC_REG_HWSPINLOCK); } val = pm_secure_status_reg_tmp.bits.data_rd; printk("addr %x, value = %x. \n", (i), val); i++; } #else while(i < STANDBY_STATUS_REG_NUM){ val = call_firmware_op(set_standby_status,TEE_SMC_PLAFORM_OPERATION, TE_SMC_STANDBY_STATUS_GET, (u32)pm_secure_status_reg, i); printk("addr %x, value = %x. \n", (i), val); i++; } #endif }
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); }
static void __init tegra_cpu_reset_handler_enable(void) { void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE); const u32 reset_address = TEGRA_IRAM_RESET_BASE + tegra_cpu_reset_handler_offset; int err; BUG_ON(is_enabled); BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE); memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start, tegra_cpu_reset_handler_size); err = call_firmware_op(set_cpu_boot_addr, 0, reset_address); switch (err) { case -ENOSYS: tegra_cpu_reset_handler_set(reset_address); /* pass-through */ case 0: is_enabled = true; break; default: pr_crit("Cannot set CPU reset handler: %d\n", err); BUG(); } }
void sun8i_set_secondary_entry(void *entry) { if (sunxi_soc_is_secure()) { call_firmware_op(set_secondary_entry, entry); } else { sunxi_set_secondary_entry(entry); } }
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; }
__u32 get_pm_secure_mem_status(void) { int val = 0; #ifndef CONFIG_SUNXI_TRUSTZONE pm_secure_status_reg_tmp.bits.reg_sel = 1; if (!hwspin_lock_timeout(MEM_RTC_REG_HWSPINLOCK, 20000)) { (*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval; pm_secure_status_reg_tmp.dwval = (*pm_secure_status_reg).dwval; hwspin_unlock(MEM_RTC_REG_HWSPINLOCK); } val = pm_secure_status_reg_tmp.bits.data_rd; return (val); #else val = call_firmware_op(set_standby_status,TEE_SMC_PLAFORM_OPERATION, TE_SMC_STANDBY_STATUS_GET, (u32)pm_secure_status_reg, 1); return (val); #endif }
static int exynos_suspend_enter(suspend_state_t state) { int ret; s3c_pm_debug_init(); S3C_PMDBG("%s: suspending the system...\n", __func__); S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__, exynos_irqwake_intmask, exynos_get_eint_wake_mask()); if (exynos_irqwake_intmask == -1U && exynos_get_eint_wake_mask() == -1U) { pr_err("%s: No wake-up sources!\n", __func__); pr_err("%s: Aborting sleep\n", __func__); return -EINVAL; } s3c_pm_save_uarts(); if (pm_data->pm_prepare) pm_data->pm_prepare(); flush_cache_all(); s3c_pm_check_store(); ret = call_firmware_op(suspend); if (ret == -ENOSYS) ret = cpu_suspend(0, pm_data->cpu_suspend); if (ret) return ret; if (pm_data->pm_resume_prepare) pm_data->pm_resume_prepare(); s3c_pm_restore_uarts(); S3C_PMDBG("%s: wakeup stat: %08x\n", __func__, pmu_raw_readl(S5P_WAKEUP_STAT)); s3c_pm_check_restore(); S3C_PMDBG("%s: resuming the system...\n", __func__); return 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); }
static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) { int i; exynos_sysram_init(); if (read_cpuid_part_number() == 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)); } } }
void save_pm_secure_mem_status_nommu(volatile __u32 val) { #ifndef CONFIG_SUNXI_TRUSTZONE if (!hwspin_lock_timeout_nommu(MEM_RTC_REG_HWSPINLOCK, 20000)) { pm_secure_status_reg_pa_tmp.bits.reg_sel = 1; pm_secure_status_reg_pa_tmp.bits.data_wr = val; (*pm_secure_status_reg_pa).dwval = pm_secure_status_reg_pa_tmp.dwval; pm_secure_status_reg_pa_tmp.bits.wr_pulse = 0; (*pm_secure_status_reg_pa).dwval = pm_secure_status_reg_pa_tmp.dwval; pm_secure_status_reg_pa_tmp.bits.wr_pulse = 1; (*pm_secure_status_reg_pa).dwval = pm_secure_status_reg_pa_tmp.dwval; pm_secure_status_reg_pa_tmp.bits.wr_pulse = 0; (*pm_secure_status_reg_pa).dwval = pm_secure_status_reg_pa_tmp.dwval; hwspin_unlock_nommu(MEM_RTC_REG_HWSPINLOCK); } return; #else call_firmware_op(set_standby_status,TEE_SMC_PLAFORM_OPERATION, TE_SMC_STANDBY_STATUS_SET, (u32)pm_secure_status_reg_pa, val); #endif }
void pm_secure_mem_status_clear(void) { #ifndef CONFIG_SUNXI_TRUSTZONE int i = 1; pm_secure_status_reg_tmp.dwval = (*pm_secure_status_reg).dwval; if (!hwspin_lock_timeout(MEM_RTC_REG_HWSPINLOCK, 20000)) { while(i < STANDBY_STATUS_REG_NUM){ pm_secure_status_reg_tmp.bits.reg_sel = i; pm_secure_status_reg_tmp.bits.data_wr = 0; (*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval; pm_secure_status_reg_tmp.bits.wr_pulse = 0; (*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval; pm_secure_status_reg_tmp.bits.wr_pulse = 1; (*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval; pm_secure_status_reg_tmp.bits.wr_pulse = 0; (*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval; i++; } hwspin_unlock(MEM_RTC_REG_HWSPINLOCK); } #else call_firmware_op(set_standby_status,TEE_SMC_PLAFORM_OPERATION, TE_SMC_STANDBY_STATUS_CLEAR, (u32)pm_secure_status_reg, 0); #endif }
static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; unsigned long phys_cpu = cpu_logical_map(cpu); /* * Set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * The secondary processor is waiting to be released from * the holding pen - release it, then wait for it to flag * that it has been released by resetting pen_release. * * Note that "pen_release" is the hardware CPU ID, whereas * "cpu" is Linux's internal ID. */ write_pen_release(phys_cpu); if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) { __raw_writel(S5P_CORE_LOCAL_PWR_EN, S5P_ARM_CORE1_CONFIGURATION); timeout = 10; /* wait max 10 ms until cpu1 is on */ while ((__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) { if (timeout-- == 0) break; mdelay(1); } if (timeout == 0) { printk(KERN_ERR "cpu1 power enable failed"); spin_unlock(&boot_lock); return -ETIMEDOUT; } } /* * Send the secondary CPU a soft interrupt, thereby causing * the boot monitor to read the system wide flags register, * and branch to the address found there. */ timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { unsigned long boot_addr; smp_rmb(); boot_addr = virt_to_phys(exynos4_secondary_startup); /* * Try to set boot address using firmware first * and fall back to boot register if it fails. */ if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr)) __raw_writel(boot_addr, cpu_boot_reg(phys_cpu)); call_firmware_op(cpu_boot, phys_cpu); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); if (pen_release == -1) break; udelay(10); } /* * now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ spin_unlock(&boot_lock); return pen_release != -1 ? -ENOSYS : 0; }
static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; u32 mpidr = cpu_logical_map(cpu); u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); int ret = -ENOSYS; /* * Set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * The secondary processor is waiting to be released from * the holding pen - release it, then wait for it to flag * that it has been released by resetting pen_release. * * Note that "pen_release" is the hardware CPU core ID, whereas * "cpu" is Linux's internal ID. */ write_pen_release(core_id); if (!soc_is_exynos5440() && !exynos_cpu_power_state(core_id)) { exynos_cpu_power_up(core_id); timeout = 10; /* wait max 10 ms until cpu1 is on */ while (exynos_cpu_power_state(core_id) != S5P_CORE_LOCAL_PWR_EN) { if (timeout-- == 0) break; mdelay(1); } if (timeout == 0) { printk(KERN_ERR "cpu1 power enable failed"); spin_unlock(&boot_lock); return -ETIMEDOUT; } } /* * Send the secondary CPU a soft interrupt, thereby causing * the boot monitor to read the system wide flags register, * and branch to the address found there. */ timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { unsigned long boot_addr; smp_rmb(); boot_addr = virt_to_phys(exynos4_secondary_startup); /* * Try to set boot address using firmware first * and fall back to boot register if it fails. */ ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr); if (ret && ret != -ENOSYS) goto fail; if (ret == -ENOSYS) { void __iomem *boot_reg = cpu_boot_reg(core_id); if (IS_ERR(boot_reg)) { ret = PTR_ERR(boot_reg); goto fail; } __raw_writel(boot_addr, cpu_boot_reg(core_id)); } call_firmware_op(cpu_boot, core_id); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); if (pen_release == -1) break; udelay(10); } /* * now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ fail: spin_unlock(&boot_lock); return pen_release != -1 ? ret : 0; }