[RFC PATCH 06/17] ARM: kernel: save/restore generic infrastructure
Lorenzo Pieralisi
lorenzo.pieralisi at arm.com
Thu Jul 7 11:50:19 EDT 2011
This patch provides the code infrastructure needed to maintain
a generic per-cpu architecture implementation of idle code.
sr_platform.c :
- code manages patchset initialization and memory management
sr_context.c:
- code initializes run-time context save/restore generic
support
sr_power.c:
- provides the generic infrastructure to enter exit low
power modes and communicate with Power Control Unit (PCU)
v7 support hinges on the basic infrastructure to provide per-cpu
arch implementation basically through standard function pointers
signatures.
Preprocessor defines include size of data needed to save/restore
L2 state. This define value should be moved to the respective
subsystem (PL310) once the patchset IF to that subsystem is settled.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
---
arch/arm/kernel/sr.h | 162 +++++++++++++++++++++++++++++++++++++++++
arch/arm/kernel/sr_context.c | 23 ++++++
arch/arm/kernel/sr_helpers.h | 56 ++++++++++++++
arch/arm/kernel/sr_platform.c | 48 ++++++++++++
arch/arm/kernel/sr_power.c | 26 +++++++
5 files changed, 315 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/kernel/sr.h
create mode 100644 arch/arm/kernel/sr_context.c
create mode 100644 arch/arm/kernel/sr_helpers.h
create mode 100644 arch/arm/kernel/sr_platform.c
create mode 100644 arch/arm/kernel/sr_power.c
diff --git a/arch/arm/kernel/sr.h b/arch/arm/kernel/sr.h
new file mode 100644
index 0000000..6b24e53
--- /dev/null
+++ b/arch/arm/kernel/sr.h
@@ -0,0 +1,162 @@
+#define SR_NR_CLUSTERS 1
+
+#define STACK_SIZE 512
+
+#define CPU_A5 0x4100c050
+#define CPU_A8 0x4100c080
+#define CPU_A9 0x410fc090
+#define L2_DATA_SIZE 16
+#define CONTEXT_SPACE_UNCACHED (2 * PAGE_SIZE)
+#define PA(f) ((typeof(f) *)virt_to_phys((void *)f))
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <asm/page.h>
+
+/*
+ * Structures we hide from the OS API
+ */
+
+struct sr_cpu_context {
+ u32 flags;
+ u32 saved_items;
+ u32 *mmu_data;
+};
+
+struct sr_cluster_context {
+ u32 saved_items;
+ u32 *l2_data;
+};
+
+struct sr_main_table {
+ pgd_t *os_mmu_context[SR_NR_CLUSTERS][CONFIG_NR_CPUS];
+ cpumask_t cpu_idle_mask[SR_NR_CLUSTERS];
+ pgd_t *fw_mmu_context;
+ u32 num_clusters;
+ struct sr_cluster *cluster_table;
+};
+
+
+/*
+ * A cluster is a container for CPUs, typically either a single CPU or a
+ * coherent cluster.
+ * We assume the CPUs in the cluster can be switched off independently.
+ */
+struct sr_cluster {
+ u32 cpu_type; /* A9mpcore, A5mpcore, etc */
+ u32 num_cpus;
+ struct sr_cluster_context *context;
+ struct sr_cpu *cpu_table;
+ u32 power_state;
+ u32 cluster_down;
+ void __iomem *scu_address;
+ void *lock;
+};
+
+struct sr_cpu {
+ struct sr_cpu_context *context;
+ u32 power_state;
+};
+
+/*
+ * arch infrastructure
+ */
+struct sr_arch {
+ unsigned int cpu_val;
+ unsigned int cpu_mask;
+
+ int (*init)(void);
+
+ int (*save_context)(struct sr_cluster *, struct sr_cpu *,
+ unsigned);
+ int (*restore_context)(struct sr_cluster *, struct sr_cpu *);
+ int (*enter_cstate)(unsigned cpu_index,
+ struct sr_cpu *cpu,
+ struct sr_cluster *cluster);
+ int (*leave_cstate)(unsigned, struct sr_cpu *,
+ struct sr_cluster *);
+ void (*reset)(void);
+
+};
+
+extern struct sr_arch *arch;
+extern int lookup_arch(void);
+
+/*
+ * Global variables
+ */
+extern struct sr_main_table main_table;
+extern unsigned long idle_save_context;
+extern unsigned long idle_restore_context;
+extern unsigned long idle_mt;
+extern void *context_memory_uncached;
+
+/*
+ * Context save/restore
+ */
+typedef u32 (sr_save_context_t)
+ (struct sr_cluster *,
+ struct sr_cpu*, u32);
+typedef u32 (sr_restore_context_t)
+ (struct sr_cluster *,
+ struct sr_cpu*);
+
+extern sr_save_context_t sr_save_context;
+extern sr_restore_context_t sr_restore_context;
+
+
+extern struct sr_arch *get_arch(void);
+
+
+/*
+ * 1:1 mappings
+ */
+
+extern int linux_sr_setup_translation_tables(void);
+
+/*
+ * dumb memory allocator
+ */
+
+extern void *get_memory(unsigned int size);
+
+/*
+ * Entering/Leaving C-states function entries
+ */
+
+extern int sr_platform_enter_cstate(unsigned cpu_index, struct sr_cpu *cpu,
+ struct sr_cluster *cluster);
+extern int sr_platform_leave_cstate(unsigned cpu_index, struct sr_cpu *cpu,
+ struct sr_cluster *cluster);
+
+/* save/restore main table */
+extern struct sr_main_table main_table;
+
+/*
+ * Init functions
+ */
+
+extern int sr_platform_runtime_init(void);
+extern int sr_platform_init(void);
+extern int sr_context_init(void);
+
+
+/*
+ * v7 specific
+ */
+
+extern char *cpu_v7_suspend_size;
+extern void scu_cpu_mode(void __iomem *base, int state);
+
+/*
+ * These arrays keep suitable stack pointers for CPUs.
+ *
+ * The memory must be 8-byte aligned.
+ */
+
+extern unsigned long platform_cpu_stacks[CONFIG_NR_CPUS];
+extern unsigned long platform_cpu_nc_stacks[CONFIG_NR_CPUS];
+#endif
diff --git a/arch/arm/kernel/sr_context.c b/arch/arm/kernel/sr_context.c
new file mode 100644
index 0000000..25eaa43
--- /dev/null
+++ b/arch/arm/kernel/sr_context.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2008-2011 ARM Limited
+ * Author(s): Jon Callan, Lorenzo Pieralisi
+ *
+ * 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/cache.h>
+#include <asm/cacheflush.h>
+#include "sr.h"
+
+int sr_context_init(void)
+{
+ idle_save_context = (unsigned long) arch->save_context;
+ idle_restore_context = __pa(arch->restore_context);
+ __cpuc_flush_dcache_area(&idle_restore_context, sizeof(unsigned long));
+ outer_clean_range(__pa(&idle_restore_context),
+ __pa(&idle_restore_context + 1));
+ return 0;
+}
diff --git a/arch/arm/kernel/sr_helpers.h b/arch/arm/kernel/sr_helpers.h
new file mode 100644
index 0000000..1ae3a9a
--- /dev/null
+++ b/arch/arm/kernel/sr_helpers.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008-2011 ARM Limited
+ * Author(s): Jon Callan, Lorenzo Pieralisi
+ *
+ * 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.
+ *
+ */
+
+static inline int sr_platform_get_cpu_index(void)
+{
+ unsigned int cpu;
+ __asm__ __volatile__(
+ "mrc p15, 0, %0, c0, c0, 5\n\t"
+ : "=r" (cpu));
+ return cpu & 0xf;
+}
+
+/*
+ * Placeholder for further extensions
+ */
+static inline int sr_platform_get_cluster_index(void)
+{
+ return 0;
+}
+
+static inline void __iomem *sr_platform_cbar(void)
+{
+ void __iomem *base;
+ __asm__ __volatile__(
+ "mrc p15, 4, %0, c15, c0, 0\n\t"
+ : "=r" (base));
+ return base;
+}
+
+#ifdef CONFIG_SMP
+static inline void exit_coherency(void)
+{
+ unsigned int v;
+ asm volatile (
+ "mrc p15, 0, %0, c1, c0, 1\n"
+ "bic %0, %0, %1\n"
+ "mcr p15, 0, %0, c1, c0, 1\n"
+ : "=&r" (v)
+ : "Ir" (0x40)
+ : );
+}
+#else
+static inline void exit_coherency(void) { }
+#endif
+
+extern void default_sleep(void);
+extern void sr_suspend(void *);
+extern void sr_resume(void *, int);
+extern void disable_clean_inv_dcache_v7_all(void);
diff --git a/arch/arm/kernel/sr_platform.c b/arch/arm/kernel/sr_platform.c
new file mode 100644
index 0000000..530aa1b
--- /dev/null
+++ b/arch/arm/kernel/sr_platform.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008-2011 ARM Limited
+ *
+ * Author(s): Jon Callan, Lorenzo Pieralisi
+ *
+ * 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/errno.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+#include <asm/sr_platform_api.h>
+#include "sr.h"
+
+void *context_memory_uncached;
+
+/*
+ * Simple memory allocator function.
+ * Returns start address of allocated region
+ * Memory is zero-initialized.
+ */
+
+static unsigned int watermark;
+
+void *get_memory(unsigned int size)
+{
+ unsigned ret;
+ void *vmem = NULL;
+
+ ret = watermark;
+ watermark += size;
+ BUG_ON(watermark >= CONTEXT_SPACE_UNCACHED);
+ vmem = (context_memory_uncached + ret);
+ watermark = ALIGN(watermark, sizeof(long long));
+
+ return vmem;
+}
+
+int sr_platform_init(void)
+{
+ memset(context_memory_uncached, 0, CONTEXT_SPACE_UNCACHED);
+ return arch->init();
+}
diff --git a/arch/arm/kernel/sr_power.c b/arch/arm/kernel/sr_power.c
new file mode 100644
index 0000000..2585559
--- /dev/null
+++ b/arch/arm/kernel/sr_power.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2008-2011 ARM Limited
+ *
+ * Author(s): Jon Callan, Lorenzo Pieralisi
+ *
+ * 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 "sr.h"
+
+int sr_platform_enter_cstate(unsigned cpu_index,
+ struct sr_cpu *cpu,
+ struct sr_cluster *cluster)
+{
+ return arch->enter_cstate(cpu_index, cpu, cluster);
+}
+
+int sr_platform_leave_cstate(unsigned cpu_index,
+ struct sr_cpu *cpu,
+ struct sr_cluster *cluster)
+{
+ return arch->leave_cstate(cpu_index, cpu, cluster);
+}
--
1.7.4.4
More information about the linux-arm-kernel
mailing list