Linux Audio

Check our new training course

Loading...
v4.6
 
  1/*
  2 *  arch/arm/mach-sti/platsmp.c
  3 *
  4 * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
  5 *		http://www.st.com
  6 *
  7 * Cloned from linux/arch/arm/mach-vexpress/platsmp.c
  8 *
  9 *  Copyright (C) 2002 ARM Ltd.
 10 *  All Rights Reserved
 11 *
 12 * This program is free software; you can redistribute it and/or modify
 13 * it under the terms of the GNU General Public License version 2 as
 14 * published by the Free Software Foundation.
 15 */
 16#include <linux/init.h>
 17#include <linux/errno.h>
 18#include <linux/delay.h>
 19#include <linux/smp.h>
 20#include <linux/io.h>
 21#include <linux/of.h>
 22#include <linux/of_address.h>
 23#include <linux/memblock.h>
 24
 25#include <asm/cacheflush.h>
 26#include <asm/smp_plat.h>
 27#include <asm/smp_scu.h>
 28
 29#include "smp.h"
 30
 31static void write_pen_release(int val)
 32{
 33	pen_release = val;
 34	smp_wmb();
 35	sync_cache_w(&pen_release);
 36}
 37
 38static DEFINE_SPINLOCK(boot_lock);
 39
 40static void sti_secondary_init(unsigned int cpu)
 41{
 42	/*
 43	 * let the primary processor know we're out of the
 44	 * pen, then head off into the C entry point
 45	 */
 46	write_pen_release(-1);
 47
 48	/*
 49	 * Synchronise with the boot thread.
 50	 */
 51	spin_lock(&boot_lock);
 52	spin_unlock(&boot_lock);
 53}
 54
 55static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
 56{
 57	unsigned long timeout;
 58
 59	/*
 60	 * set synchronisation state between this boot processor
 61	 * and the secondary one
 62	 */
 63	spin_lock(&boot_lock);
 64
 65	/*
 66	 * The secondary processor is waiting to be released from
 67	 * the holding pen - release it, then wait for it to flag
 68	 * that it has been released by resetting pen_release.
 69	 *
 70	 * Note that "pen_release" is the hardware CPU ID, whereas
 71	 * "cpu" is Linux's internal ID.
 72	 */
 73	write_pen_release(cpu_logical_map(cpu));
 74
 75	/*
 76	 * Send the secondary CPU a soft interrupt, thereby causing
 77	 * it to jump to the secondary entrypoint.
 
 
 78	 */
 79	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 80
 81	timeout = jiffies + (1 * HZ);
 82	while (time_before(jiffies, timeout)) {
 83		smp_rmb();
 84		if (pen_release == -1)
 85			break;
 86
 87		udelay(10);
 88	}
 89
 90	/*
 91	 * now the secondary core is starting up let it run its
 92	 * calibrations, then wait for it to finish
 93	 */
 94	spin_unlock(&boot_lock);
 95
 96	return pen_release != -1 ? -ENOSYS : 0;
 97}
 98
 99static void __init sti_smp_prepare_cpus(unsigned int max_cpus)
100{
101	struct device_node *np;
102	void __iomem *scu_base;
103	u32 __iomem *cpu_strt_ptr;
104	u32 release_phys;
105	int cpu;
106	unsigned long entry_pa = virt_to_phys(sti_secondary_startup);
107
108	np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
109
110	if (np) {
111		scu_base = of_iomap(np, 0);
112		scu_enable(scu_base);
113		of_node_put(np);
114	}
115
116	if (max_cpus <= 1)
117		return;
118
119	for_each_possible_cpu(cpu) {
120
121		np = of_get_cpu_node(cpu, NULL);
122
123		if (!np)
124			continue;
125
126		if (of_property_read_u32(np, "cpu-release-addr",
127						&release_phys)) {
128			pr_err("CPU %d: missing or invalid cpu-release-addr "
129				"property\n", cpu);
130			continue;
131		}
132
133		/*
134		 * holding pen is usually configured in SBC DMEM but can also be
135		 * in RAM.
136		 */
137
138		if (!memblock_is_memory(release_phys))
139			cpu_strt_ptr =
140				ioremap(release_phys, sizeof(release_phys));
141		else
142			cpu_strt_ptr =
143				(u32 __iomem *)phys_to_virt(release_phys);
144
145		__raw_writel(entry_pa, cpu_strt_ptr);
146
147		/*
148		 * wmb so that data is actually written
149		 * before cache flush is done
150		 */
151		smp_wmb();
152		sync_cache_w(cpu_strt_ptr);
153
154		if (!memblock_is_memory(release_phys))
155			iounmap(cpu_strt_ptr);
156	}
157}
158
159const struct smp_operations sti_smp_ops __initconst = {
160	.smp_prepare_cpus	= sti_smp_prepare_cpus,
161	.smp_secondary_init	= sti_secondary_init,
162	.smp_boot_secondary	= sti_boot_secondary,
163};
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 *  arch/arm/mach-sti/platsmp.c
  4 *
  5 * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
  6 *		http://www.st.com
  7 *
  8 * Cloned from linux/arch/arm/mach-vexpress/platsmp.c
  9 *
 10 *  Copyright (C) 2002 ARM Ltd.
 11 *  All Rights Reserved
 
 
 
 
 12 */
 13#include <linux/init.h>
 14#include <linux/errno.h>
 15#include <linux/delay.h>
 16#include <linux/smp.h>
 17#include <linux/io.h>
 18#include <linux/of.h>
 19#include <linux/of_address.h>
 20#include <linux/memblock.h>
 21
 22#include <asm/cacheflush.h>
 23#include <asm/smp_plat.h>
 24#include <asm/smp_scu.h>
 25
 26#include "smp.h"
 27
 28static u32 __iomem *cpu_strt_ptr;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 29
 30static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
 31{
 32	unsigned long entry_pa = __pa_symbol(secondary_startup);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 33
 34	/*
 35	 * Secondary CPU is initialised and started by a U-BOOTROM firmware.
 36	 * Secondary CPU is spinning and waiting for a write at cpu_strt_ptr.
 37	 * Writing secondary_startup address at cpu_strt_ptr makes it to
 38	 * jump directly to secondary_startup().
 39	 */
 40	__raw_writel(entry_pa, cpu_strt_ptr);
 41
 42	/* wmb so that data is actually written before cache flush is done */
 43	smp_wmb();
 44	sync_cache_w(cpu_strt_ptr);
 
 
 
 
 
 
 
 
 
 
 
 45
 46	return 0;
 47}
 48
 49static void __init sti_smp_prepare_cpus(unsigned int max_cpus)
 50{
 51	struct device_node *np;
 52	void __iomem *scu_base;
 
 53	u32 release_phys;
 54	int cpu;
 
 55
 56	np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
 57
 58	if (np) {
 59		scu_base = of_iomap(np, 0);
 60		scu_enable(scu_base);
 61		of_node_put(np);
 62	}
 63
 64	if (max_cpus <= 1)
 65		return;
 66
 67	for_each_possible_cpu(cpu) {
 68
 69		np = of_get_cpu_node(cpu, NULL);
 70
 71		if (!np)
 72			continue;
 73
 74		if (of_property_read_u32(np, "cpu-release-addr",
 75						&release_phys)) {
 76			pr_err("CPU %d: missing or invalid cpu-release-addr "
 77				"property\n", cpu);
 78			continue;
 79		}
 80
 81		/*
 82		 * cpu-release-addr is usually configured in SBC DMEM but can
 83		 * also be in RAM.
 84		 */
 85
 86		if (!memblock_is_memory(release_phys))
 87			cpu_strt_ptr =
 88				ioremap(release_phys, sizeof(release_phys));
 89		else
 90			cpu_strt_ptr =
 91				(u32 __iomem *)phys_to_virt(release_phys);
 92
 93		set_cpu_possible(cpu, true);
 
 
 
 
 
 
 
 
 
 
 94	}
 95}
 96
 97const struct smp_operations sti_smp_ops __initconst = {
 98	.smp_prepare_cpus	= sti_smp_prepare_cpus,
 
 99	.smp_boot_secondary	= sti_boot_secondary,
100};