Highbank platform updates for 3.13
- convert Calxeda cpuidle driver to a platform driver and to use PSCI - convert highbank smp_ops and suspend to PSCI -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQEcBAABAgAGBQJSYCG/AAoJEMhvYp4jgsXiFkkIALhWCtYC7qcthorB/s9STVkv 5VhPA7Jx9i9omnrsdzICXYC/HQaSN7gwgAPICYxTcAcen+qySHeXvk7jWh7PtQJ9 OHLWd1tYVxLV1y9tnmiFYVbJn017W0Kq0m4kkZEh6Q8KW0qE1xcHGREWHs/+1D4k Rx798Tg6jgjt0nvg893aAcFQsgKxG53n5uqNySI9DKvxYcJBJkHD0/EgyHk+myVY TPZj6f9xGwLCv0rQU6Vr29NniX1w2bRt6lYEp0KGlGjEGbiuStcRf6xUUmhxmDCs faIspFMxpR4dqqeIq1Xh2x8S4QOMjDoiFGZmGBgrNdvLNOGNsd+QRhdLJiXuB88= =8WVt -----END PGP SIGNATURE----- Merge tag 'highbank-for-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux into next/soc From Rob Herring: Highbank platform updates for 3.13 - convert Calxeda cpuidle driver to a platform driver and to use PSCI - convert highbank smp_ops and suspend to PSCI * tag 'highbank-for-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: dts: calxeda: add ARM PSCI binding ARM: highbank: adapt to use ARM PSCI calls ARM: PSCI: remove unnecessary include of arm-gic.h cpuidle: calxeda: add support to use PSCI calls ARM: highbank: cpuidle: convert to platform driver cpuidle: calxeda: add cpu_pm_enter/exit calls
This commit is contained in:
commit
cb1110ca79
|
@ -19,6 +19,14 @@
|
|||
bootargs = "console=ttyAMA0";
|
||||
};
|
||||
|
||||
psci {
|
||||
compatible = "arm,psci";
|
||||
method = "smc";
|
||||
cpu_suspend = <0x84000002>;
|
||||
cpu_off = <0x84000004>;
|
||||
cpu_on = <0x84000006>;
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/irqchip/arm-gic.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ config ARCH_HIGHBANK
|
|||
select ARM_ERRATA_775420
|
||||
select ARM_ERRATA_798181
|
||||
select ARM_GIC
|
||||
select ARM_PSCI
|
||||
select ARM_TIMER_SP804
|
||||
select CACHE_L2X0
|
||||
select CLKDEV_LOOKUP
|
||||
|
|
|
@ -3,6 +3,4 @@ obj-y := highbank.o system.o smc.o
|
|||
plus_sec := $(call as-instr,.arch_extension sec,+sec)
|
||||
AFLAGS_smc.o :=-Wa,-march=armv7-a$(plus_sec)
|
||||
|
||||
obj-$(CONFIG_SMP) += platsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
obj-$(CONFIG_PM_SLEEP) += pm.o
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include <linux/reboot.h>
|
||||
|
||||
extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
|
||||
extern void highbank_restart(enum reboot_mode, const char *);
|
||||
extern void __iomem *scu_base_addr;
|
||||
|
||||
|
@ -14,8 +13,5 @@ static inline void highbank_pm_init(void) {}
|
|||
#endif
|
||||
|
||||
extern void highbank_smc1(int fn, int arg);
|
||||
extern void highbank_cpu_die(unsigned int cpu);
|
||||
|
||||
extern struct smp_operations highbank_smp_ops;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,10 +25,9 @@
|
|||
#include <linux/of_address.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/psci.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
@ -49,17 +48,6 @@ static void __init highbank_scu_map_io(void)
|
|||
scu_base_addr = ioremap(base, SZ_4K);
|
||||
}
|
||||
|
||||
#define HB_JUMP_TABLE_PHYS(cpu) (0x40 + (0x10 * (cpu)))
|
||||
#define HB_JUMP_TABLE_VIRT(cpu) phys_to_virt(HB_JUMP_TABLE_PHYS(cpu))
|
||||
|
||||
void highbank_set_cpu_jump(int cpu, void *jump_addr)
|
||||
{
|
||||
cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0);
|
||||
writel(virt_to_phys(jump_addr), HB_JUMP_TABLE_VIRT(cpu));
|
||||
__cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
|
||||
outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
|
||||
HB_JUMP_TABLE_PHYS(cpu) + 15);
|
||||
}
|
||||
|
||||
static void highbank_l2x0_disable(void)
|
||||
{
|
||||
|
@ -153,6 +141,10 @@ static struct notifier_block highbank_platform_nb = {
|
|||
.notifier_call = highbank_platform_notifier,
|
||||
};
|
||||
|
||||
static struct platform_device highbank_cpuidle_device = {
|
||||
.name = "cpuidle-calxeda",
|
||||
};
|
||||
|
||||
static void __init highbank_init(void)
|
||||
{
|
||||
pm_power_off = highbank_power_off;
|
||||
|
@ -162,6 +154,9 @@ static void __init highbank_init(void)
|
|||
bus_register_notifier(&amba_bustype, &highbank_amba_nb);
|
||||
|
||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
||||
|
||||
if (psci_ops.cpu_suspend)
|
||||
platform_device_register(&highbank_cpuidle_device);
|
||||
}
|
||||
|
||||
static const char *highbank_match[] __initconst = {
|
||||
|
@ -174,7 +169,6 @@ DT_MACHINE_START(HIGHBANK, "Highbank")
|
|||
#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
|
||||
.dma_zone_size = (4ULL * SZ_1G),
|
||||
#endif
|
||||
.smp = smp_ops(highbank_smp_ops),
|
||||
.init_irq = highbank_init_irq,
|
||||
.init_time = highbank_timer_init,
|
||||
.init_machine = highbank_init,
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Calxeda, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "sysregs.h"
|
||||
|
||||
extern void secondary_startup(void);
|
||||
|
||||
/*
|
||||
* platform-specific code to shutdown a CPU
|
||||
*
|
||||
*/
|
||||
void __ref highbank_cpu_die(unsigned int cpu)
|
||||
{
|
||||
highbank_set_cpu_jump(cpu, phys_to_virt(0));
|
||||
|
||||
flush_cache_louis();
|
||||
highbank_set_core_pwr();
|
||||
|
||||
while (1)
|
||||
cpu_do_idle();
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright 2010-2011 Calxeda, Inc.
|
||||
* Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/smp_scu.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
extern void secondary_startup(void);
|
||||
|
||||
static int highbank_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
highbank_set_cpu_jump(cpu, secondary_startup);
|
||||
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the CPU possible map early - this describes the CPUs
|
||||
* which may be present or become present in the system.
|
||||
*/
|
||||
static void __init highbank_smp_init_cpus(void)
|
||||
{
|
||||
unsigned int i, ncores = 4;
|
||||
|
||||
/* sanity check */
|
||||
if (ncores > NR_CPUS) {
|
||||
printk(KERN_WARNING
|
||||
"highbank: no. of cores (%d) greater than configured "
|
||||
"maximum of %d - clipping\n",
|
||||
ncores, NR_CPUS);
|
||||
ncores = NR_CPUS;
|
||||
}
|
||||
|
||||
for (i = 0; i < ncores; i++)
|
||||
set_cpu_possible(i, true);
|
||||
}
|
||||
|
||||
static void __init highbank_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
if (scu_base_addr)
|
||||
scu_enable(scu_base_addr);
|
||||
}
|
||||
|
||||
struct smp_operations highbank_smp_ops __initdata = {
|
||||
.smp_init_cpus = highbank_smp_init_cpus,
|
||||
.smp_prepare_cpus = highbank_smp_prepare_cpus,
|
||||
.smp_boot_secondary = highbank_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_die = highbank_cpu_die,
|
||||
#endif
|
||||
};
|
|
@ -16,27 +16,19 @@
|
|||
|
||||
#include <linux/cpu_pm.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/proc-fns.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "sysregs.h"
|
||||
#include <asm/psci.h>
|
||||
|
||||
static int highbank_suspend_finish(unsigned long val)
|
||||
{
|
||||
outer_flush_all();
|
||||
outer_disable();
|
||||
const struct psci_power_state ps = {
|
||||
.type = PSCI_POWER_STATE_TYPE_POWER_DOWN,
|
||||
.affinity_level = 1,
|
||||
};
|
||||
|
||||
highbank_set_pwr_suspend();
|
||||
|
||||
cpu_do_idle();
|
||||
|
||||
highbank_clear_pwr_request();
|
||||
return 0;
|
||||
return psci_ops.cpu_suspend(ps, __pa(cpu_resume));
|
||||
}
|
||||
|
||||
static int highbank_pm_enter(suspend_state_t state)
|
||||
|
@ -44,15 +36,11 @@ static int highbank_pm_enter(suspend_state_t state)
|
|||
cpu_pm_enter();
|
||||
cpu_cluster_pm_enter();
|
||||
|
||||
highbank_set_cpu_jump(0, cpu_resume);
|
||||
cpu_suspend(0, highbank_suspend_finish);
|
||||
|
||||
cpu_cluster_pm_exit();
|
||||
cpu_pm_exit();
|
||||
|
||||
highbank_smc1(0x102, 0x1);
|
||||
if (scu_base_addr)
|
||||
scu_enable(scu_base_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -63,5 +51,8 @@ static const struct platform_suspend_ops highbank_pm_ops = {
|
|||
|
||||
void __init highbank_pm_init(void)
|
||||
{
|
||||
if (!psci_ops.cpu_suspend)
|
||||
return;
|
||||
|
||||
suspend_set_ops(&highbank_pm_ops);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
config ARM_HIGHBANK_CPUIDLE
|
||||
bool "CPU Idle Driver for Calxeda processors"
|
||||
depends on ARCH_HIGHBANK
|
||||
depends on ARM_PSCI
|
||||
select ARM_CPU_SUSPEND
|
||||
help
|
||||
Select this to enable cpuidle on Calxeda processors.
|
||||
|
|
|
@ -21,53 +21,30 @@
|
|||
*/
|
||||
|
||||
#include <linux/cpuidle.h>
|
||||
#include <linux/cpu_pm.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/cpuidle.h>
|
||||
#include <asm/proc-fns.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/suspend.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cp15.h>
|
||||
|
||||
extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
|
||||
extern void __iomem *scu_base_addr;
|
||||
|
||||
static noinline void calxeda_idle_restore(void)
|
||||
{
|
||||
set_cr(get_cr() | CR_C);
|
||||
set_auxcr(get_auxcr() | 0x40);
|
||||
scu_power_mode(scu_base_addr, SCU_PM_NORMAL);
|
||||
}
|
||||
#include <asm/psci.h>
|
||||
|
||||
static int calxeda_idle_finish(unsigned long val)
|
||||
{
|
||||
/* Already flushed cache, but do it again as the outer cache functions
|
||||
* dirty the cache with spinlocks */
|
||||
flush_cache_all();
|
||||
|
||||
set_auxcr(get_auxcr() & ~0x40);
|
||||
set_cr(get_cr() & ~CR_C);
|
||||
|
||||
scu_power_mode(scu_base_addr, SCU_PM_DORMANT);
|
||||
|
||||
cpu_do_idle();
|
||||
|
||||
/* Restore things if we didn't enter power-gating */
|
||||
calxeda_idle_restore();
|
||||
return 1;
|
||||
const struct psci_power_state ps = {
|
||||
.type = PSCI_POWER_STATE_TYPE_POWER_DOWN,
|
||||
};
|
||||
return psci_ops.cpu_suspend(ps, __pa(cpu_resume));
|
||||
}
|
||||
|
||||
static int calxeda_pwrdown_idle(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv,
|
||||
int index)
|
||||
{
|
||||
highbank_set_cpu_jump(smp_processor_id(), cpu_resume);
|
||||
cpu_pm_enter();
|
||||
cpu_suspend(0, calxeda_idle_finish);
|
||||
cpu_pm_exit();
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@ -88,11 +65,17 @@ static struct cpuidle_driver calxeda_idle_driver = {
|
|||
.state_count = 2,
|
||||
};
|
||||
|
||||
static int __init calxeda_cpuidle_init(void)
|
||||
static int __init calxeda_cpuidle_probe(struct platform_device *pdev)
|
||||
{
|
||||
if (!of_machine_is_compatible("calxeda,highbank"))
|
||||
return -ENODEV;
|
||||
|
||||
return cpuidle_register(&calxeda_idle_driver, NULL);
|
||||
}
|
||||
module_init(calxeda_cpuidle_init);
|
||||
|
||||
static struct platform_driver calxeda_cpuidle_plat_driver = {
|
||||
.driver = {
|
||||
.name = "cpuidle-calxeda",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = calxeda_cpuidle_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(calxeda_cpuidle_plat_driver);
|
||||
|
|
Loading…
Reference in New Issue