forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/arch/mips/kernel/smp-cps.c
....@@ -1,11 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2013 Imagination Technologies
34 * Author: Paul Burton <paul.burton@mips.com>
4
- *
5
- * This program is free software; you can redistribute it and/or modify it
6
- * under the terms of the GNU General Public License as published by the
7
- * Free Software Foundation; either version 2 of the License, or (at your
8
- * option) any later version.
95 */
106
117 #include <linux/cpu.h>
....@@ -398,6 +394,55 @@
398394 local_irq_enable();
399395 }
400396
397
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC)
398
+
399
+enum cpu_death {
400
+ CPU_DEATH_HALT,
401
+ CPU_DEATH_POWER,
402
+};
403
+
404
+static void cps_shutdown_this_cpu(enum cpu_death death)
405
+{
406
+ unsigned int cpu, core, vpe_id;
407
+
408
+ cpu = smp_processor_id();
409
+ core = cpu_core(&cpu_data[cpu]);
410
+
411
+ if (death == CPU_DEATH_HALT) {
412
+ vpe_id = cpu_vpe_id(&cpu_data[cpu]);
413
+
414
+ pr_debug("Halting core %d VP%d\n", core, vpe_id);
415
+ if (cpu_has_mipsmt) {
416
+ /* Halt this TC */
417
+ write_c0_tchalt(TCHALT_H);
418
+ instruction_hazard();
419
+ } else if (cpu_has_vp) {
420
+ write_cpc_cl_vp_stop(1 << vpe_id);
421
+
422
+ /* Ensure that the VP_STOP register is written */
423
+ wmb();
424
+ }
425
+ } else {
426
+ pr_debug("Gating power to core %d\n", core);
427
+ /* Power down the core */
428
+ cps_pm_enter_state(CPS_PM_POWER_GATED);
429
+ }
430
+}
431
+
432
+#ifdef CONFIG_KEXEC
433
+
434
+static void cps_kexec_nonboot_cpu(void)
435
+{
436
+ if (cpu_has_mipsmt || cpu_has_vp)
437
+ cps_shutdown_this_cpu(CPU_DEATH_HALT);
438
+ else
439
+ cps_shutdown_this_cpu(CPU_DEATH_POWER);
440
+}
441
+
442
+#endif /* CONFIG_KEXEC */
443
+
444
+#endif /* CONFIG_HOTPLUG_CPU || CONFIG_KEXEC */
445
+
401446 #ifdef CONFIG_HOTPLUG_CPU
402447
403448 static int cps_cpu_disable(void)
....@@ -421,19 +466,15 @@
421466 }
422467
423468 static unsigned cpu_death_sibling;
424
-static enum {
425
- CPU_DEATH_HALT,
426
- CPU_DEATH_POWER,
427
-} cpu_death;
469
+static enum cpu_death cpu_death;
428470
429471 void play_dead(void)
430472 {
431
- unsigned int cpu, core, vpe_id;
473
+ unsigned int cpu;
432474
433475 local_irq_disable();
434476 idle_task_exit();
435477 cpu = smp_processor_id();
436
- core = cpu_core(&cpu_data[cpu]);
437478 cpu_death = CPU_DEATH_POWER;
438479
439480 pr_debug("CPU%d going offline\n", cpu);
....@@ -456,25 +497,7 @@
456497 /* This CPU has chosen its way out */
457498 (void)cpu_report_death();
458499
459
- if (cpu_death == CPU_DEATH_HALT) {
460
- vpe_id = cpu_vpe_id(&cpu_data[cpu]);
461
-
462
- pr_debug("Halting core %d VP%d\n", core, vpe_id);
463
- if (cpu_has_mipsmt) {
464
- /* Halt this TC */
465
- write_c0_tchalt(TCHALT_H);
466
- instruction_hazard();
467
- } else if (cpu_has_vp) {
468
- write_cpc_cl_vp_stop(1 << vpe_id);
469
-
470
- /* Ensure that the VP_STOP register is written */
471
- wmb();
472
- }
473
- } else {
474
- pr_debug("Gating power to core %d\n", core);
475
- /* Power down the core */
476
- cps_pm_enter_state(CPS_PM_POWER_GATED);
477
- }
500
+ cps_shutdown_this_cpu(cpu_death);
478501
479502 /* This should never be reached */
480503 panic("Failed to offline CPU %u", cpu);
....@@ -593,6 +616,9 @@
593616 .cpu_disable = cps_cpu_disable,
594617 .cpu_die = cps_cpu_die,
595618 #endif
619
+#ifdef CONFIG_KEXEC
620
+ .kexec_nonboot_cpu = cps_kexec_nonboot_cpu,
621
+#endif
596622 };
597623
598624 bool mips_cps_smp_in_use(void)