mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
ARM: rockchip: support cpu hotplug and basic PM
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
obj-y += common.o
|
||||
obj-y += cpu.o
|
||||
obj-y += rk3188.o
|
||||
obj-$(CONFIG_PM) += pm.o
|
||||
obj-$(CONFIG_RK_FPGA) += fpga.o
|
||||
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
obj-$(CONFIG_FIQ_DEBUGGER) += rk_fiq_debugger.o
|
||||
obj-$(CONFIG_CPU_FREQ) += rk3188-cpufreq.o
|
||||
obj-$(CONFIG_DVFS) += dvfs.o
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
extern unsigned long rockchip_boot_fn;
|
||||
extern struct smp_operations rockchip_smp_ops;
|
||||
|
||||
extern int rockchip_cpu_kill(unsigned int cpu);
|
||||
extern void rockchip_cpu_die(unsigned int cpu);
|
||||
extern int rockchip_cpu_disable(unsigned int cpu);
|
||||
|
||||
#define BOOT_MODE_NORMAL 0
|
||||
#define BOOT_MODE_FACTORY2 1
|
||||
#define BOOT_MODE_RECOVERY 2
|
||||
@@ -17,5 +21,6 @@ extern struct smp_operations rockchip_smp_ops;
|
||||
extern int rockchip_boot_mode(void);
|
||||
extern void __init rockchip_boot_mode_init(u32 flag, u32 mode);
|
||||
extern void rockchip_restart_get_boot_mode(const char *cmd, u32 *flag, u32 *mode);
|
||||
extern void __init rockchip_suspend_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
97
arch/arm/mach-rockchip/hotplug.c
Normal file
97
arch/arm/mach-rockchip/hotplug.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014 ROCKCHIP, Inc.
|
||||
* Copyright (C) 2002 ARM Ltd.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cp15.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "pmu.h"
|
||||
|
||||
static cpumask_t dead_cpus;
|
||||
|
||||
int rockchip_cpu_kill(unsigned int cpu)
|
||||
{
|
||||
int k;
|
||||
|
||||
/* this function is running on another CPU than the offline target,
|
||||
* here we need wait for shutdown code in platform_cpu_die() to
|
||||
* finish before asking SoC-specific code to power off the CPU core.
|
||||
*/
|
||||
for (k = 0; k < 1000; k++) {
|
||||
if (cpumask_test_cpu(cpu, &dead_cpus)) {
|
||||
mdelay(1);
|
||||
rockchip_pmu_ops.set_power_domain(PD_CPU_0 + cpu, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* platform-specific code to shutdown a CPU
|
||||
*
|
||||
* Called with IRQs disabled
|
||||
*/
|
||||
void rockchip_cpu_die(unsigned int cpu)
|
||||
{
|
||||
unsigned int v;
|
||||
|
||||
/* hardware shutdown code running on the CPU that is being offlined */
|
||||
flush_cache_all();
|
||||
dsb();
|
||||
|
||||
/* notify platform_cpu_kill() that hardware shutdown is finished */
|
||||
cpumask_set_cpu(cpu, &dead_cpus);
|
||||
flush_cache_louis();
|
||||
|
||||
asm volatile(
|
||||
" mcr p15, 0, %1, c7, c5, 0\n"
|
||||
" mcr p15, 0, %1, c7, c10, 4\n"
|
||||
/*
|
||||
* Turn off coherency
|
||||
*/
|
||||
" mrc p15, 0, %0, c1, c0, 1\n"
|
||||
" bic %0, %0, %3\n" // clear ACTLR.SMP | ACTLR.FW
|
||||
" mcr p15, 0, %0, c1, c0, 1\n"
|
||||
" mrc p15, 0, %0, c1, c0, 0\n"
|
||||
" bic %0, %0, %2\n"
|
||||
" mcr p15, 0, %0, c1, c0, 0\n"
|
||||
: "=&r" (v)
|
||||
: "r" (0), "Ir" (CR_C), "Ir" ((1 << 6) | (1 << 0))
|
||||
: "cc");
|
||||
|
||||
/* wait for SoC code in platform_cpu_kill() to shut off CPU core
|
||||
* power. CPU bring up starts from the reset vector.
|
||||
*/
|
||||
while (1) {
|
||||
dsb();
|
||||
wfi();
|
||||
}
|
||||
}
|
||||
|
||||
int rockchip_cpu_disable(unsigned int cpu)
|
||||
{
|
||||
cpumask_clear_cpu(cpu, &dead_cpus);
|
||||
/*
|
||||
* we don't allow CPU 0 to be shutdown (it is still too special
|
||||
* e.g. clock tick interrupts)
|
||||
*/
|
||||
return cpu == 0 ? -EPERM : 0;
|
||||
}
|
||||
@@ -156,4 +156,9 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
|
||||
struct smp_operations rockchip_smp_ops __initdata = {
|
||||
.smp_prepare_cpus = rockchip_smp_prepare_cpus,
|
||||
.smp_boot_secondary = rockchip_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_kill = rockchip_cpu_kill,
|
||||
.cpu_die = rockchip_cpu_die,
|
||||
.cpu_disable = rockchip_cpu_disable,
|
||||
#endif
|
||||
};
|
||||
|
||||
17
arch/arm/mach-rockchip/pm.c
Normal file
17
arch/arm/mach-rockchip/pm.c
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <linux/suspend.h>
|
||||
|
||||
static int rockchip_suspend_enter(suspend_state_t state)
|
||||
{
|
||||
cpu_do_idle();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_suspend_ops rockchip_suspend_ops = {
|
||||
.valid = suspend_valid_only_mem,
|
||||
.enter = rockchip_suspend_enter,
|
||||
};
|
||||
|
||||
void __init rockchip_suspend_init(void)
|
||||
{
|
||||
suspend_set_ops(&rockchip_suspend_ops);
|
||||
}
|
||||
@@ -329,6 +329,7 @@ DT_MACHINE_START(RK3188_DT, "RK30board")
|
||||
.map_io = rk3188_dt_map_io,
|
||||
.init_time = rk3188_dt_init_timer,
|
||||
.dt_compat = rk3188_dt_compat,
|
||||
.init_late = rockchip_suspend_init,
|
||||
.restart = rk3188_restart,
|
||||
MACHINE_END
|
||||
|
||||
|
||||
Reference in New Issue
Block a user