// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2002 ARM Ltd. * All Rights Reserved * Copyright (c) 2010, Code Aurora Forum. All rights reserved. * Copyright (c) 2014 The Linux Foundation. All rights reserved.
*/
base = of_iomap(node, 0);
of_node_put(node); if (!base) return -ENOMEM;
writel_relaxed(0, base + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
writel_relaxed(0, base + SCSS_CPU1CORE_RESET);
writel_relaxed(3, base + SCSS_DBG_STATUS_CORE_PWRDUP);
mb();
iounmap(base);
return 0;
}
staticint cortex_a7_release_secondary(unsignedint cpu)
{ int ret = 0; void __iomem *reg; struct device_node *cpu_node, *acc_node;
u32 reg_val;
cpu_node = of_get_cpu_node(cpu, NULL); if (!cpu_node) return -ENODEV;
acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); if (!acc_node) {
ret = -ENODEV; goto out_acc;
}
reg = of_iomap(acc_node, 0); if (!reg) {
ret = -ENOMEM; goto out_acc_map;
}
/* Put the CPU into reset. */
reg_val = CORE_RST | COREPOR_RST | CLAMP | CORE_MEM_CLAMP;
writel(reg_val, reg + APCS_CPU_PWR_CTL);
/* Turn on the BHS and set the BHS_CNT to 16 XO clock cycles */
writel(BHS_EN | (0x10 << BHS_CNT_SHIFT), reg + APC_PWR_GATE_CTL); /* Wait for the BHS to settle */
udelay(2);
/* Release CPU out of reset and bring it to life. */
reg_val &= ~(CORE_RST | COREPOR_RST);
writel(reg_val, reg + APCS_CPU_PWR_CTL);
reg_val |= CORE_PWRD_UP;
writel(reg_val, reg + APCS_CPU_PWR_CTL);
cpu_node = of_get_cpu_node(cpu, NULL); if (!cpu_node) return -ENODEV;
acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); if (!acc_node) {
ret = -ENODEV; goto out_acc;
}
l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0); if (!l2_node) {
ret = -ENODEV; goto out_l2;
}
saw_node = of_parse_phandle(l2_node, "qcom,saw", 0); if (!saw_node) {
ret = -ENODEV; goto out_saw;
}
reg = of_iomap(acc_node, 0); if (!reg) {
ret = -ENOMEM; goto out_map;
}
l2_saw_base = of_iomap(saw_node, 0); if (!l2_saw_base) {
ret = -ENOMEM; goto out_saw_map;
}
/* Turn on the BHS, turn off LDO Bypass and power down LDO */
reg_val = (64 << BHS_CNT_SHIFT) | (0x3f << LDO_PWR_DWN_SHIFT) | BHS_EN;
writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
mb(); /* wait for the BHS to settle */
udelay(1);
/* Turn on BHS segments */
reg_val |= 0x3f << BHS_SEG_SHIFT;
writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
mb(); /* wait for the BHS to settle */
udelay(1);
/* Finally turn on the bypass so that BHS supplies power */
reg_val |= 0x3f << LDO_BYP_SHIFT;
writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
staticint qcom_boot_secondary(unsignedint cpu, int (*func)(unsignedint))
{ int ret = 0;
if (!per_cpu(cold_boot_done, cpu)) {
ret = func(cpu); if (!ret)
per_cpu(cold_boot_done, cpu) = true;
}
/* * 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.
*/
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
staticvoid __init qcom_smp_prepare_cpus(unsignedint max_cpus)
{ int cpu;
if (qcom_scm_set_cold_boot_addr(secondary_startup_arm)) {
for_each_present_cpu(cpu) { if (cpu == smp_processor_id()) continue;
set_cpu_present(cpu, false);
}
pr_warn("Failed to set CPU boot address, disabling SMP\n");
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.