diff options
Diffstat (limited to 'arch/arm/mach-highbank')
| -rw-r--r-- | arch/arm/mach-highbank/Kconfig | 19 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/Makefile | 5 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/Makefile.boot | 1 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/clock.c | 62 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/core.h | 18 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/highbank.c | 196 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/hotplug.c | 56 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/include/mach/debug-macro.S | 19 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/include/mach/gpio.h | 1 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/include/mach/timex.h | 6 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/include/mach/uncompress.h | 9 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/lluart.c | 34 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/platsmp.c | 78 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/pm.c | 31 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/sysregs.h | 42 | ||||
| -rw-r--r-- | arch/arm/mach-highbank/system.c | 14 |
16 files changed, 204 insertions, 387 deletions
diff --git a/arch/arm/mach-highbank/Kconfig b/arch/arm/mach-highbank/Kconfig new file mode 100644 index 00000000000..a5960e2ac09 --- /dev/null +++ b/arch/arm/mach-highbank/Kconfig @@ -0,0 +1,19 @@ +config ARCH_HIGHBANK + bool "Calxeda ECX-1000/2000 (Highbank/Midway)" if ARCH_MULTI_V7 + select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE + select ARCH_HAS_HOLES_MEMORYMODEL + select ARCH_HAS_OPP + select ARCH_SUPPORTS_BIG_ENDIAN + select ARM_AMBA + select ARM_ERRATA_764369 if SMP + select ARM_ERRATA_775420 + select ARM_ERRATA_798181 if SMP + select ARM_GIC + select ARM_PSCI + select ARM_TIMER_SP804 + select CACHE_L2X0 + select HAVE_ARM_SCU + select HAVE_ARM_TWD if SMP + select MAILBOX + select PL320_MBOX + select ZONE_DMA if ARM_LPAE diff --git a/arch/arm/mach-highbank/Makefile b/arch/arm/mach-highbank/Makefile index ded4652ada8..55840f414d3 100644 --- a/arch/arm/mach-highbank/Makefile +++ b/arch/arm/mach-highbank/Makefile @@ -1,9 +1,6 @@ -obj-y := clock.o highbank.o system.o smc.o +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_DEBUG_HIGHBANK_UART) += lluart.o -obj-$(CONFIG_SMP) += platsmp.o -obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_PM_SLEEP) += pm.o diff --git a/arch/arm/mach-highbank/Makefile.boot b/arch/arm/mach-highbank/Makefile.boot deleted file mode 100644 index dae9661a768..00000000000 --- a/arch/arm/mach-highbank/Makefile.boot +++ /dev/null @@ -1 +0,0 @@ -zreladdr-y := 0x00008000 diff --git a/arch/arm/mach-highbank/clock.c b/arch/arm/mach-highbank/clock.c deleted file mode 100644 index c25a2ae4fde..00000000000 --- a/arch/arm/mach-highbank/clock.c +++ /dev/null @@ -1,62 +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/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/clk.h> -#include <linux/clkdev.h> - -struct clk { - unsigned long rate; -}; - -int clk_enable(struct clk *clk) -{ - return 0; -} - -void clk_disable(struct clk *clk) -{} - -unsigned long clk_get_rate(struct clk *clk) -{ - return clk->rate; -} - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - return clk->rate; -} - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - return 0; -} - -static struct clk eclk = { .rate = 200000000 }; -static struct clk pclk = { .rate = 150000000 }; - -static struct clk_lookup lookups[] = { - { .clk = &pclk, .con_id = "apb_pclk", }, - { .clk = &pclk, .dev_id = "sp804", }, - { .clk = &eclk, .dev_id = "ffe0e000.sdhci", }, - { .clk = &pclk, .dev_id = "fff36000.serial", }, -}; - -void __init highbank_clocks_init(void) -{ - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); -} diff --git a/arch/arm/mach-highbank/core.h b/arch/arm/mach-highbank/core.h index 141ed517182..7ec5edcd133 100644 --- a/arch/arm/mach-highbank/core.h +++ b/arch/arm/mach-highbank/core.h @@ -1,11 +1,17 @@ -extern void highbank_set_cpu_jump(int cpu, void *jump_addr); -extern void highbank_clocks_init(void); -extern void highbank_restart(char, const char *); +#ifndef __HIGHBANK_CORE_H +#define __HIGHBANK_CORE_H + +#include <linux/reboot.h> + +extern void highbank_restart(enum reboot_mode, const char *); extern void __iomem *scu_base_addr; -#ifdef CONFIG_DEBUG_HIGHBANK_UART -extern void highbank_lluart_map_io(void); + +#ifdef CONFIG_PM_SLEEP +extern void highbank_pm_init(void); #else -static inline void highbank_lluart_map_io(void) {} +static inline void highbank_pm_init(void) {} #endif extern void highbank_smc1(int fn, int arg); + +#endif diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 8777612b1a4..8c35ae4ff17 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -15,41 +15,30 @@ */ #include <linux/clk.h> #include <linux/clkdev.h> +#include <linux/clocksource.h> +#include <linux/dma-mapping.h> +#include <linux/input.h> #include <linux/io.h> -#include <linux/irq.h> -#include <linux/irqdomain.h> +#include <linux/irqchip.h> +#include <linux/mailbox.h> #include <linux/of.h> #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/of_address.h> -#include <linux/smp.h> - -#include <asm/cacheflush.h> -#include <asm/smp_plat.h> -#include <asm/smp_scu.h> -#include <asm/smp_twd.h> -#include <asm/hardware/arm_timer.h> -#include <asm/hardware/timer-sp.h> -#include <asm/hardware/gic.h> +#include <linux/reboot.h> +#include <linux/amba/bus.h> +#include <linux/platform_device.h> + +#include <asm/psci.h> #include <asm/hardware/cache-l2x0.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> -#include <asm/mach/time.h> #include "core.h" #include "sysregs.h" void __iomem *sregs_base; - -#define HB_SCU_VIRT_BASE 0xfee00000 -void __iomem *scu_base_addr = ((void __iomem *)(HB_SCU_VIRT_BASE)); - -static struct map_desc scu_io_desc __initdata = { - .virtual = HB_SCU_VIRT_BASE, - .pfn = 0, /* run-time */ - .length = SZ_4K, - .type = MT_DEVICE, -}; +void __iomem *scu_base_addr; static void __init highbank_scu_map_io(void) { @@ -58,107 +47,142 @@ static void __init highbank_scu_map_io(void) /* Get SCU base */ asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base)); - scu_io_desc.pfn = __phys_to_pfn(base); - iotable_init(&scu_io_desc, 1); -} - -static void __init highbank_map_io(void) -{ - highbank_scu_map_io(); - highbank_lluart_map_io(); + 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) +static void highbank_l2c310_write_sec(unsigned long val, unsigned reg) { - cpu = cpu_logical_map(cpu); - 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); + if (reg == L2X0_CTRL) + highbank_smc1(0x102, val); + else + WARN_ONCE(1, "Highbank L2C310: ignoring write to reg 0x%x\n", + reg); } -const static struct of_device_id irq_match[] = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {} -}; - -#ifdef CONFIG_CACHE_L2X0 -static void highbank_l2x0_disable(void) -{ - /* Disable PL310 L2 Cache controller */ - highbank_smc1(0x102, 0x0); -} -#endif - static void __init highbank_init_irq(void) { - of_irq_init(irq_match); + irqchip_init(); -#ifdef CONFIG_CACHE_L2X0 - /* Enable PL310 L2 Cache controller */ - highbank_smc1(0x102, 0x1); - l2x0_of_init(0, ~0UL); - outer_cache.disable = highbank_l2x0_disable; -#endif + if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9")) + highbank_scu_map_io(); } -static void __init highbank_timer_init(void) +static void highbank_power_off(void) { - int irq; - struct device_node *np; - void __iomem *timer_base; + highbank_set_pwr_shutdown(); - /* Map system registers */ - np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs"); - sregs_base = of_iomap(np, 0); - WARN_ON(!sregs_base); - - np = of_find_compatible_node(NULL, NULL, "arm,sp804"); - timer_base = of_iomap(np, 0); - WARN_ON(!timer_base); - irq = irq_of_parse_and_map(np, 0); + while (1) + cpu_do_idle(); +} - highbank_clocks_init(); +static int highbank_platform_notifier(struct notifier_block *nb, + unsigned long event, void *__dev) +{ + struct resource *res; + int reg = -1; + u32 val; + struct device *dev = __dev; + + if (event != BUS_NOTIFY_ADD_DEVICE) + return NOTIFY_DONE; + + if (of_device_is_compatible(dev->of_node, "calxeda,hb-ahci")) + reg = 0xc; + else if (of_device_is_compatible(dev->of_node, "calxeda,hb-sdhci")) + reg = 0x18; + else if (of_device_is_compatible(dev->of_node, "arm,pl330")) + reg = 0x20; + else if (of_device_is_compatible(dev->of_node, "calxeda,hb-xgmac")) { + res = platform_get_resource(to_platform_device(dev), + IORESOURCE_MEM, 0); + if (res) { + if (res->start == 0xfff50000) + reg = 0; + else if (res->start == 0xfff51000) + reg = 4; + } + } + + if (reg < 0) + return NOTIFY_DONE; + + if (of_property_read_bool(dev->of_node, "dma-coherent")) { + val = readl(sregs_base + reg); + writel(val | 0xff01, sregs_base + reg); + set_dma_ops(dev, &arm_coherent_dma_ops); + } + + return NOTIFY_OK; +} - sp804_clocksource_and_sched_clock_init(timer_base + 0x20, "timer1"); - sp804_clockevents_init(timer_base, irq, "timer0"); +static struct notifier_block highbank_amba_nb = { + .notifier_call = highbank_platform_notifier, +}; - twd_local_timer_of_register(); -} +static struct notifier_block highbank_platform_nb = { + .notifier_call = highbank_platform_notifier, +}; -static struct sys_timer highbank_timer = { - .init = highbank_timer_init, +static struct platform_device highbank_cpuidle_device = { + .name = "cpuidle-calxeda", }; -static void highbank_power_off(void) +static int hb_keys_notifier(struct notifier_block *nb, unsigned long event, void *data) { - hignbank_set_pwr_shutdown(); - scu_power_mode(scu_base_addr, SCU_PM_POWEROFF); + u32 key = *(u32 *)data; - while (1) - cpu_do_idle(); + if (event != 0x1000) + return 0; + + if (key == KEY_POWER) + orderly_poweroff(false); + else if (key == 0xffff) + ctrl_alt_del(); + + return 0; } +static struct notifier_block hb_keys_nb = { + .notifier_call = hb_keys_notifier, +}; static void __init highbank_init(void) { + struct device_node *np; + + /* Map system registers */ + np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs"); + sregs_base = of_iomap(np, 0); + WARN_ON(!sregs_base); + pm_power_off = highbank_power_off; + highbank_pm_init(); + + bus_register_notifier(&platform_bus_type, &highbank_platform_nb); + bus_register_notifier(&amba_bustype, &highbank_amba_nb); + + pl320_ipc_register_notifier(&hb_keys_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 = { "calxeda,highbank", + "calxeda,ecx-2000", NULL, }; DT_MACHINE_START(HIGHBANK, "Highbank") - .map_io = highbank_map_io, +#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE) + .dma_zone_size = (4ULL * SZ_1G), +#endif + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, + .l2c_write_sec = highbank_l2c310_write_sec, .init_irq = highbank_init_irq, - .timer = &highbank_timer, - .handle_irq = gic_handle_irq, .init_machine = highbank_init, .dt_compat = highbank_match, .restart = highbank_restart, diff --git a/arch/arm/mach-highbank/hotplug.c b/arch/arm/mach-highbank/hotplug.c deleted file mode 100644 index 977cebbea58..00000000000 --- a/arch/arm/mach-highbank/hotplug.c +++ /dev/null @@ -1,56 +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 <linux/errno.h> -#include <linux/smp.h> - -#include <asm/smp_scu.h> -#include <asm/cacheflush.h> - -#include "core.h" - -extern void secondary_startup(void); - -int platform_cpu_kill(unsigned int cpu) -{ - return 1; -} - -/* - * platform-specific code to shutdown a CPU - * - */ -void platform_cpu_die(unsigned int cpu) -{ - flush_cache_all(); - - highbank_set_cpu_jump(cpu, secondary_startup); - scu_power_mode(scu_base_addr, SCU_PM_POWEROFF); - - cpu_do_idle(); - - /* We should never return from idle */ - panic("highbank: cpu %d unexpectedly exit from shutdown\n", cpu); -} - -int platform_cpu_disable(unsigned int cpu) -{ - /* - * CPU0 should not be shut down via hotplug. cpu_idle can WFI - * or a proper shutdown or hibernate should be used. - */ - return cpu == 0 ? -EPERM : 0; -} diff --git a/arch/arm/mach-highbank/include/mach/debug-macro.S b/arch/arm/mach-highbank/include/mach/debug-macro.S deleted file mode 100644 index cb57fe5bcd0..00000000000 --- a/arch/arm/mach-highbank/include/mach/debug-macro.S +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Debugging macro include header - * - * Copyright (C) 1994-1999 Russell King - * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks - * - * 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. - */ - - .macro addruart,rp,rv,tmp - movw \rv, #0x6000 - movt \rv, #0xfee3 - movw \rp, #0x6000 - movt \rp, #0xfff3 - .endm - -#include <asm/hardware/debug-pl01x.S> diff --git a/arch/arm/mach-highbank/include/mach/gpio.h b/arch/arm/mach-highbank/include/mach/gpio.h deleted file mode 100644 index 40a8c178f10..00000000000 --- a/arch/arm/mach-highbank/include/mach/gpio.h +++ /dev/null @@ -1 +0,0 @@ -/* empty */ diff --git a/arch/arm/mach-highbank/include/mach/timex.h b/arch/arm/mach-highbank/include/mach/timex.h deleted file mode 100644 index 88dac7a55a9..00000000000 --- a/arch/arm/mach-highbank/include/mach/timex.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __MACH_TIMEX_H -#define __MACH_TIMEX_H - -#define CLOCK_TICK_RATE 1000000 - -#endif diff --git a/arch/arm/mach-highbank/include/mach/uncompress.h b/arch/arm/mach-highbank/include/mach/uncompress.h deleted file mode 100644 index bbe20e69632..00000000000 --- a/arch/arm/mach-highbank/include/mach/uncompress.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __MACH_UNCOMPRESS_H -#define __MACH_UNCOMPRESS_H - -#define putc(c) -#define flush() -#define arch_decomp_setup() -#define arch_decomp_wdog() - -#endif diff --git a/arch/arm/mach-highbank/lluart.c b/arch/arm/mach-highbank/lluart.c deleted file mode 100644 index 371575019f3..00000000000 --- a/arch/arm/mach-highbank/lluart.c +++ /dev/null @@ -1,34 +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/init.h> -#include <asm/page.h> -#include <asm/sizes.h> -#include <asm/mach/map.h> - -#define HB_DEBUG_LL_PHYS_BASE 0xfff36000 -#define HB_DEBUG_LL_VIRT_BASE 0xfee36000 - -static struct map_desc lluart_io_desc __initdata = { - .virtual = HB_DEBUG_LL_VIRT_BASE, - .pfn = __phys_to_pfn(HB_DEBUG_LL_PHYS_BASE), - .length = SZ_4K, - .type = MT_DEVICE, -}; - -void __init highbank_lluart_map_io(void) -{ - iotable_init(&lluart_io_desc, 1); -} diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c deleted file mode 100644 index d01364c72b4..00000000000 --- a/arch/arm/mach-highbank/platsmp.c +++ /dev/null @@ -1,78 +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 <asm/hardware/gic.h> - -#include "core.h" - -extern void secondary_startup(void); - -void __cpuinit platform_secondary_init(unsigned int cpu) -{ - gic_secondary_init(0); -} - -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) -{ - gic_raise_softirq(cpumask_of(cpu), 0); - return 0; -} - -/* - * Initialise the CPU possible map early - this describes the CPUs - * which may be present or become present in the system. - */ -void __init smp_init_cpus(void) -{ - unsigned int i, ncores; - - ncores = scu_get_core_count(scu_base_addr); - - /* 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); - - set_smp_cross_call(gic_raise_softirq); -} - -void __init platform_smp_prepare_cpus(unsigned int max_cpus) -{ - int i; - - scu_enable(scu_base_addr); - - /* - * Write the address of secondary startup into the jump table - * The cores are in wfi and wait until they receive a soft interrupt - * and a non-zero value to jump to. Then the secondary CPU branches - * to this address. - */ - for (i = 1; i < max_cpus; i++) - highbank_set_cpu_jump(i, secondary_startup); -} diff --git a/arch/arm/mach-highbank/pm.c b/arch/arm/mach-highbank/pm.c index 33b3beb8998..7f2bd85eb93 100644 --- a/arch/arm/mach-highbank/pm.c +++ b/arch/arm/mach-highbank/pm.c @@ -14,31 +14,33 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <linux/cpu_pm.h> #include <linux/init.h> -#include <linux/io.h> #include <linux/suspend.h> -#include <asm/proc-fns.h> -#include <asm/smp_scu.h> #include <asm/suspend.h> - -#include "core.h" -#include "sysregs.h" +#include <asm/psci.h> static int highbank_suspend_finish(unsigned long val) { - cpu_do_idle(); - return 0; + const struct psci_power_state ps = { + .type = PSCI_POWER_STATE_TYPE_POWER_DOWN, + .affinity_level = 1, + }; + + return psci_ops.cpu_suspend(ps, __pa(cpu_resume)); } static int highbank_pm_enter(suspend_state_t state) { - hignbank_set_pwr_suspend(); - highbank_set_cpu_jump(0, cpu_resume); + cpu_pm_enter(); + cpu_cluster_pm_enter(); - scu_power_mode(scu_base_addr, SCU_PM_POWEROFF); cpu_suspend(0, highbank_suspend_finish); + cpu_cluster_pm_exit(); + cpu_pm_exit(); + return 0; } @@ -47,9 +49,10 @@ static const struct platform_suspend_ops highbank_pm_ops = { .valid = suspend_valid_only_mem, }; -static int __init highbank_pm_init(void) +void __init highbank_pm_init(void) { + if (!psci_ops.cpu_suspend) + return; + suspend_set_ops(&highbank_pm_ops); - return 0; } -module_init(highbank_pm_init); diff --git a/arch/arm/mach-highbank/sysregs.h b/arch/arm/mach-highbank/sysregs.h index 0e913389f44..5995df7f262 100644 --- a/arch/arm/mach-highbank/sysregs.h +++ b/arch/arm/mach-highbank/sysregs.h @@ -17,6 +17,10 @@ #define _MACH_HIGHBANK__SYSREGS_H_ #include <linux/io.h> +#include <linux/smp.h> +#include <asm/smp_plat.h> +#include <asm/smp_scu.h> +#include "core.h" extern void __iomem *sregs_base; @@ -29,24 +33,54 @@ extern void __iomem *sregs_base; #define HB_PWR_HARD_RESET 2 #define HB_PWR_SHUTDOWN 3 -static inline void hignbank_set_pwr_suspend(void) +#define SREG_CPU_PWR_CTRL(c) (0x200 + ((c) * 4)) + +static inline void highbank_set_core_pwr(void) +{ + int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(smp_processor_id()), 0); + if (scu_base_addr) + scu_power_mode(scu_base_addr, SCU_PM_POWEROFF); + else + writel_relaxed(1, sregs_base + SREG_CPU_PWR_CTRL(cpu)); +} + +static inline void highbank_clear_core_pwr(void) +{ + int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(smp_processor_id()), 0); + if (scu_base_addr) + scu_power_mode(scu_base_addr, SCU_PM_NORMAL); + else + writel_relaxed(0, sregs_base + SREG_CPU_PWR_CTRL(cpu)); +} + +static inline void highbank_set_pwr_suspend(void) { writel(HB_PWR_SUSPEND, sregs_base + HB_SREG_A9_PWR_REQ); + highbank_set_core_pwr(); } -static inline void hignbank_set_pwr_shutdown(void) +static inline void highbank_set_pwr_shutdown(void) { writel(HB_PWR_SHUTDOWN, sregs_base + HB_SREG_A9_PWR_REQ); + highbank_set_core_pwr(); } -static inline void hignbank_set_pwr_soft_reset(void) +static inline void highbank_set_pwr_soft_reset(void) { writel(HB_PWR_SOFT_RESET, sregs_base + HB_SREG_A9_PWR_REQ); + highbank_set_core_pwr(); } -static inline void hignbank_set_pwr_hard_reset(void) +static inline void highbank_set_pwr_hard_reset(void) { writel(HB_PWR_HARD_RESET, sregs_base + HB_SREG_A9_PWR_REQ); + highbank_set_core_pwr(); +} + +static inline void highbank_clear_pwr_request(void) +{ + writel(~0UL, sregs_base + HB_SREG_A9_PWR_REQ); + highbank_clear_core_pwr(); } #endif diff --git a/arch/arm/mach-highbank/system.c b/arch/arm/mach-highbank/system.c index 82c27230d4a..2df5870b758 100644 --- a/arch/arm/mach-highbank/system.c +++ b/arch/arm/mach-highbank/system.c @@ -14,20 +14,20 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/io.h> -#include <asm/smp_scu.h> #include <asm/proc-fns.h> +#include <linux/reboot.h> #include "core.h" #include "sysregs.h" -void highbank_restart(char mode, const char *cmd) +void highbank_restart(enum reboot_mode mode, const char *cmd) { - if (mode == 'h') - hignbank_set_pwr_hard_reset(); + if (mode == REBOOT_HARD) + highbank_set_pwr_hard_reset(); else - hignbank_set_pwr_soft_reset(); + highbank_set_pwr_soft_reset(); - scu_power_mode(scu_base_addr, SCU_PM_POWEROFF); - cpu_do_idle(); + while (1) + cpu_do_idle(); } |
