diff options
Diffstat (limited to 'kernel/arch/arm/plat-versatile')
-rw-r--r-- | kernel/arch/arm/plat-versatile/Kconfig | 9 | ||||
-rw-r--r-- | kernel/arch/arm/plat-versatile/Makefile | 5 | ||||
-rw-r--r-- | kernel/arch/arm/plat-versatile/clock.c | 74 | ||||
-rw-r--r-- | kernel/arch/arm/plat-versatile/headsmp.S | 41 | ||||
-rw-r--r-- | kernel/arch/arm/plat-versatile/include/plat/clock.h | 15 | ||||
-rw-r--r-- | kernel/arch/arm/plat-versatile/include/plat/platsmp.h | 14 | ||||
-rw-r--r-- | kernel/arch/arm/plat-versatile/include/plat/sched_clock.h | 6 | ||||
-rw-r--r-- | kernel/arch/arm/plat-versatile/platsmp.c | 91 | ||||
-rw-r--r-- | kernel/arch/arm/plat-versatile/sched-clock.c | 41 |
9 files changed, 296 insertions, 0 deletions
diff --git a/kernel/arch/arm/plat-versatile/Kconfig b/kernel/arch/arm/plat-versatile/Kconfig new file mode 100644 index 000000000..49b8ef915 --- /dev/null +++ b/kernel/arch/arm/plat-versatile/Kconfig @@ -0,0 +1,9 @@ +if PLAT_VERSATILE + +config PLAT_VERSATILE_CLOCK + bool + +config PLAT_VERSATILE_SCHED_CLOCK + bool + +endif diff --git a/kernel/arch/arm/plat-versatile/Makefile b/kernel/arch/arm/plat-versatile/Makefile new file mode 100644 index 000000000..03c4900ac --- /dev/null +++ b/kernel/arch/arm/plat-versatile/Makefile @@ -0,0 +1,5 @@ +ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include + +obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o +obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o +obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/kernel/arch/arm/plat-versatile/clock.c b/kernel/arch/arm/plat-versatile/clock.c new file mode 100644 index 000000000..5c8b6564f --- /dev/null +++ b/kernel/arch/arm/plat-versatile/clock.c @@ -0,0 +1,74 @@ +/* + * linux/arch/arm/plat-versatile/clock.c + * + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * 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/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/clk.h> +#include <linux/mutex.h> + +#include <asm/hardware/icst.h> + +#include <mach/clkdev.h> + +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + long ret = -EIO; + if (clk->ops && clk->ops->round) + ret = clk->ops->round(clk, rate); + return ret; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EIO; + if (clk->ops && clk->ops->set) + ret = clk->ops->set(clk, rate); + return ret; +} +EXPORT_SYMBOL(clk_set_rate); + +long icst_clk_round(struct clk *clk, unsigned long rate) +{ + struct icst_vco vco; + vco = icst_hz_to_vco(clk->params, rate); + return icst_hz(clk->params, vco); +} +EXPORT_SYMBOL(icst_clk_round); + +int icst_clk_set(struct clk *clk, unsigned long rate) +{ + struct icst_vco vco; + + vco = icst_hz_to_vco(clk->params, rate); + clk->rate = icst_hz(clk->params, vco); + clk->ops->setvco(clk, vco); + + return 0; +} +EXPORT_SYMBOL(icst_clk_set); diff --git a/kernel/arch/arm/plat-versatile/headsmp.S b/kernel/arch/arm/plat-versatile/headsmp.S new file mode 100644 index 000000000..40f27e52d --- /dev/null +++ b/kernel/arch/arm/plat-versatile/headsmp.S @@ -0,0 +1,41 @@ +/* + * linux/arch/arm/plat-versatile/headsmp.S + * + * Copyright (c) 2003 ARM Limited + * 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/linkage.h> +#include <linux/init.h> +#include <asm/assembler.h> + +/* + * Realview/Versatile Express specific entry point for secondary CPUs. + * This provides a "holding pen" into which all secondary cores are held + * until we're ready for them to initialise. + */ +ENTRY(versatile_secondary_startup) + ARM_BE8(setend be) + mrc p15, 0, r0, c0, c0, 5 + bic r0, #0xff000000 + adr r4, 1f + ldmia r4, {r5, r6} + sub r4, r4, r5 + add r6, r6, r4 +pen: ldr r7, [r6] + cmp r7, r0 + bne pen + + /* + * we've been released from the holding pen: secondary_stack + * should now contain the SVC stack for this core + */ + b secondary_startup + + .align +1: .long . + .long pen_release +ENDPROC(versatile_secondary_startup) diff --git a/kernel/arch/arm/plat-versatile/include/plat/clock.h b/kernel/arch/arm/plat-versatile/include/plat/clock.h new file mode 100644 index 000000000..3cfb024cc --- /dev/null +++ b/kernel/arch/arm/plat-versatile/include/plat/clock.h @@ -0,0 +1,15 @@ +#ifndef PLAT_CLOCK_H +#define PLAT_CLOCK_H + +#include <asm/hardware/icst.h> + +struct clk_ops { + long (*round)(struct clk *, unsigned long); + int (*set)(struct clk *, unsigned long); + void (*setvco)(struct clk *, struct icst_vco); +}; + +int icst_clk_set(struct clk *, unsigned long); +long icst_clk_round(struct clk *, unsigned long); + +#endif diff --git a/kernel/arch/arm/plat-versatile/include/plat/platsmp.h b/kernel/arch/arm/plat-versatile/include/plat/platsmp.h new file mode 100644 index 000000000..50fb83019 --- /dev/null +++ b/kernel/arch/arm/plat-versatile/include/plat/platsmp.h @@ -0,0 +1,14 @@ +/* + * linux/arch/arm/plat-versatile/include/plat/platsmp.h + * + * Copyright (C) 2011 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. + */ + +extern void versatile_secondary_startup(void); +extern void versatile_secondary_init(unsigned int cpu); +extern int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle); diff --git a/kernel/arch/arm/plat-versatile/include/plat/sched_clock.h b/kernel/arch/arm/plat-versatile/include/plat/sched_clock.h new file mode 100644 index 000000000..5c3e4fc9f --- /dev/null +++ b/kernel/arch/arm/plat-versatile/include/plat/sched_clock.h @@ -0,0 +1,6 @@ +#ifndef ARM_PLAT_SCHED_CLOCK_H +#define ARM_PLAT_SCHED_CLOCK_H + +void versatile_sched_clock_init(void __iomem *, unsigned long); + +#endif diff --git a/kernel/arch/arm/plat-versatile/platsmp.c b/kernel/arch/arm/plat-versatile/platsmp.c new file mode 100644 index 000000000..b4a8d54fc --- /dev/null +++ b/kernel/arch/arm/plat-versatile/platsmp.c @@ -0,0 +1,91 @@ +/* + * linux/arch/arm/plat-versatile/platsmp.c + * + * 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/init.h> +#include <linux/errno.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/jiffies.h> +#include <linux/smp.h> + +#include <asm/cacheflush.h> +#include <asm/smp_plat.h> + +/* + * Write pen_release in a way that is guaranteed to be visible to all + * observers, irrespective of whether they're taking part in coherency + * or not. This is necessary for the hotplug code to work reliably. + */ +static void write_pen_release(int val) +{ + pen_release = val; + smp_wmb(); + sync_cache_w(&pen_release); +} + +static DEFINE_RAW_SPINLOCK(boot_lock); + +void versatile_secondary_init(unsigned int cpu) +{ + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + write_pen_release(-1); + + /* + * Synchronise with the boot thread. + */ + raw_spin_lock(&boot_lock); + raw_spin_unlock(&boot_lock); +} + +int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + + /* + * Set synchronisation state between this boot processor + * and the secondary one + */ + raw_spin_lock(&boot_lock); + + /* + * This is really belt and braces; we hold unintended secondary + * CPUs in the holding pen until we're ready for them. However, + * since we haven't sent them a soft interrupt, they shouldn't + * be there. + */ + write_pen_release(cpu_logical_map(cpu)); + + /* + * Send the secondary CPU a soft interrupt, thereby causing + * the boot monitor to read the system wide flags register, + * and branch to the address found there. + */ + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + smp_rmb(); + if (pen_release == -1) + break; + + udelay(10); + } + + /* + * now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + raw_spin_unlock(&boot_lock); + + return pen_release != -1 ? -ENOSYS : 0; +} diff --git a/kernel/arch/arm/plat-versatile/sched-clock.c b/kernel/arch/arm/plat-versatile/sched-clock.c new file mode 100644 index 000000000..c966ae90f --- /dev/null +++ b/kernel/arch/arm/plat-versatile/sched-clock.c @@ -0,0 +1,41 @@ +/* + * linux/arch/arm/plat-versatile/sched-clock.c + * + * Copyright (C) 1999 - 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/sched_clock.h> + +#include <plat/sched_clock.h> + +static void __iomem *ctr; + +static u64 notrace versatile_read_sched_clock(void) +{ + if (ctr) + return readl(ctr); + + return 0; +} + +void __init versatile_sched_clock_init(void __iomem *reg, unsigned long rate) +{ + ctr = reg; + sched_clock_register(versatile_read_sched_clock, 32, rate); +} |