Linux Audio

Check our new training course

Loading...
v6.9.4
 1// SPDX-License-Identifier: GPL-2.0-only
 2/*
 3 * linux/arch/arm/mach-vexpress/mcpm_platsmp.c
 4 *
 5 * Created by:  Nicolas Pitre, November 2012
 6 * Copyright:   (C) 2012-2013  Linaro Limited
 7 *
 
 
 
 
 8 * Code to handle secondary CPU bringup and hotplug for the cluster power API.
 9 */
10
11#include <linux/init.h>
12#include <linux/smp.h>
13#include <linux/spinlock.h>
14
15#include <asm/mcpm.h>
16#include <asm/smp.h>
17#include <asm/smp_plat.h>
18
19static void cpu_to_pcpu(unsigned int cpu,
20			unsigned int *pcpu, unsigned int *pcluster)
21{
22	unsigned int mpidr;
23
24	mpidr = cpu_logical_map(cpu);
25	*pcpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
26	*pcluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
27}
28
29static int mcpm_boot_secondary(unsigned int cpu, struct task_struct *idle)
30{
31	unsigned int pcpu, pcluster, ret;
32	extern void secondary_startup(void);
33
34	cpu_to_pcpu(cpu, &pcpu, &pcluster);
35
36	pr_debug("%s: logical CPU %d is physical CPU %d cluster %d\n",
37		 __func__, cpu, pcpu, pcluster);
38
39	mcpm_set_entry_vector(pcpu, pcluster, NULL);
40	ret = mcpm_cpu_power_up(pcpu, pcluster);
41	if (ret)
42		return ret;
43	mcpm_set_entry_vector(pcpu, pcluster, secondary_startup);
44	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
45	dsb_sev();
46	return 0;
47}
48
49static void mcpm_secondary_init(unsigned int cpu)
50{
51	mcpm_cpu_powered_up();
52}
53
54#ifdef CONFIG_HOTPLUG_CPU
55
56static int mcpm_cpu_kill(unsigned int cpu)
57{
58	unsigned int pcpu, pcluster;
59
60	cpu_to_pcpu(cpu, &pcpu, &pcluster);
61
62	return !mcpm_wait_for_cpu_powerdown(pcpu, pcluster);
63}
64
65static bool mcpm_cpu_can_disable(unsigned int cpu)
66{
67	/* We assume all CPUs may be shut down. */
68	return true;
 
 
 
 
69}
70
71static void mcpm_cpu_die(unsigned int cpu)
72{
73	unsigned int mpidr, pcpu, pcluster;
74	mpidr = read_cpuid_mpidr();
75	pcpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
76	pcluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
77	mcpm_set_entry_vector(pcpu, pcluster, NULL);
78	mcpm_cpu_power_down();
79}
80
81#endif
82
83static const struct smp_operations mcpm_smp_ops __initconst = {
84	.smp_boot_secondary	= mcpm_boot_secondary,
85	.smp_secondary_init	= mcpm_secondary_init,
86#ifdef CONFIG_HOTPLUG_CPU
87	.cpu_kill		= mcpm_cpu_kill,
88	.cpu_can_disable	= mcpm_cpu_can_disable,
89	.cpu_die		= mcpm_cpu_die,
90#endif
91};
92
93void __init mcpm_smp_set_ops(void)
94{
95	smp_set_ops(&mcpm_smp_ops);
96}
v3.15
 
  1/*
  2 * linux/arch/arm/mach-vexpress/mcpm_platsmp.c
  3 *
  4 * Created by:  Nicolas Pitre, November 2012
  5 * Copyright:   (C) 2012-2013  Linaro Limited
  6 *
  7 * This program is free software; you can redistribute it and/or modify
  8 * it under the terms of the GNU General Public License version 2 as
  9 * published by the Free Software Foundation.
 10 *
 11 * Code to handle secondary CPU bringup and hotplug for the cluster power API.
 12 */
 13
 14#include <linux/init.h>
 15#include <linux/smp.h>
 16#include <linux/spinlock.h>
 17
 18#include <asm/mcpm.h>
 19#include <asm/smp.h>
 20#include <asm/smp_plat.h>
 21
 22static void cpu_to_pcpu(unsigned int cpu,
 23			unsigned int *pcpu, unsigned int *pcluster)
 24{
 25	unsigned int mpidr;
 26
 27	mpidr = cpu_logical_map(cpu);
 28	*pcpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
 29	*pcluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
 30}
 31
 32static int mcpm_boot_secondary(unsigned int cpu, struct task_struct *idle)
 33{
 34	unsigned int pcpu, pcluster, ret;
 35	extern void secondary_startup(void);
 36
 37	cpu_to_pcpu(cpu, &pcpu, &pcluster);
 38
 39	pr_debug("%s: logical CPU %d is physical CPU %d cluster %d\n",
 40		 __func__, cpu, pcpu, pcluster);
 41
 42	mcpm_set_entry_vector(pcpu, pcluster, NULL);
 43	ret = mcpm_cpu_power_up(pcpu, pcluster);
 44	if (ret)
 45		return ret;
 46	mcpm_set_entry_vector(pcpu, pcluster, secondary_startup);
 47	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 48	dsb_sev();
 49	return 0;
 50}
 51
 52static void mcpm_secondary_init(unsigned int cpu)
 53{
 54	mcpm_cpu_powered_up();
 55}
 56
 57#ifdef CONFIG_HOTPLUG_CPU
 58
 59static int mcpm_cpu_kill(unsigned int cpu)
 60{
 61	unsigned int pcpu, pcluster;
 62
 63	cpu_to_pcpu(cpu, &pcpu, &pcluster);
 64
 65	return !mcpm_cpu_power_down_finish(pcpu, pcluster);
 66}
 67
 68static int mcpm_cpu_disable(unsigned int cpu)
 69{
 70	/*
 71	 * We assume all CPUs may be shut down.
 72	 * This would be the hook to use for eventual Secure
 73	 * OS migration requests as described in the PSCI spec.
 74	 */
 75	return 0;
 76}
 77
 78static void mcpm_cpu_die(unsigned int cpu)
 79{
 80	unsigned int mpidr, pcpu, pcluster;
 81	mpidr = read_cpuid_mpidr();
 82	pcpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
 83	pcluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
 84	mcpm_set_entry_vector(pcpu, pcluster, NULL);
 85	mcpm_cpu_power_down();
 86}
 87
 88#endif
 89
 90static struct smp_operations __initdata mcpm_smp_ops = {
 91	.smp_boot_secondary	= mcpm_boot_secondary,
 92	.smp_secondary_init	= mcpm_secondary_init,
 93#ifdef CONFIG_HOTPLUG_CPU
 94	.cpu_kill		= mcpm_cpu_kill,
 95	.cpu_disable		= mcpm_cpu_disable,
 96	.cpu_die		= mcpm_cpu_die,
 97#endif
 98};
 99
100void __init mcpm_smp_set_ops(void)
101{
102	smp_set_ops(&mcpm_smp_ops);
103}