help
          This options enables support for the ARM timer and watchdog unit
 
+config MCPM
+       bool "Multi-Cluster Power Management"
+       depends on CPU_V7 && SMP
+       help
+         This option provides the common power management infrastructure
+         for (multi-)cluster based systems, such as big.LITTLE based
+         systems.
+
 choice
        prompt "Memory split"
        default VMSPLIT_3G
 
 obj-$(CONFIG_SHARP_SCOOP)      += scoop.o
 obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
 obj-$(CONFIG_ARM_TIMER_SP804)  += timer-sp.o
+obj-$(CONFIG_MCPM)             += mcpm_head.o mcpm_entry.o
 
--- /dev/null
+/*
+ * arch/arm/common/mcpm_entry.c -- entry point for multi-cluster PM
+ *
+ * Created by:  Nicolas Pitre, March 2012
+ * Copyright:   (C) 2012-2013  Linaro 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 <asm/mcpm.h>
+#include <asm/cacheflush.h>
+
+extern unsigned long mcpm_entry_vectors[MAX_NR_CLUSTERS][MAX_CPUS_PER_CLUSTER];
+
+void mcpm_set_entry_vector(unsigned cpu, unsigned cluster, void *ptr)
+{
+       unsigned long val = ptr ? virt_to_phys(ptr) : 0;
+       mcpm_entry_vectors[cluster][cpu] = val;
+       sync_cache_w(&mcpm_entry_vectors[cluster][cpu]);
+}
 
--- /dev/null
+/*
+ * arch/arm/common/mcpm_head.S -- kernel entry point for multi-cluster PM
+ *
+ * Created by:  Nicolas Pitre, March 2012
+ * Copyright:   (C) 2012-2013  Linaro 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/linkage.h>
+#include <asm/mcpm.h>
+
+       .macro  pr_dbg  string
+#if defined(CONFIG_DEBUG_LL) && defined(DEBUG)
+       b       1901f
+1902:  .asciz  "CPU"
+1903:  .asciz  " cluster"
+1904:  .asciz  ": \string"
+       .align
+1901:  adr     r0, 1902b
+       bl      printascii
+       mov     r0, r9
+       bl      printhex8
+       adr     r0, 1903b
+       bl      printascii
+       mov     r0, r10
+       bl      printhex8
+       adr     r0, 1904b
+       bl      printascii
+#endif
+       .endm
+
+       .arm
+       .align
+
+ENTRY(mcpm_entry_point)
+
+ THUMB(        adr     r12, BSYM(1f)   )
+ THUMB(        bx      r12             )
+ THUMB(        .thumb                  )
+1:
+       mrc     p15, 0, r0, c0, c0, 5           @ MPIDR
+       ubfx    r9, r0, #0, #8                  @ r9 = cpu
+       ubfx    r10, r0, #8, #8                 @ r10 = cluster
+       mov     r3, #MAX_CPUS_PER_CLUSTER
+       mla     r4, r3, r10, r9                 @ r4 = canonical CPU index
+       cmp     r4, #(MAX_CPUS_PER_CLUSTER * MAX_NR_CLUSTERS)
+       blo     2f
+
+       /* We didn't expect this CPU.  Try to cheaply make it quiet. */
+1:     wfi
+       wfe
+       b       1b
+
+2:     pr_dbg  "kernel mcpm_entry_point\n"
+
+       /*
+        * MMU is off so we need to get to mcpm_entry_vectors in a
+        * position independent way.
+        */
+       adr     r5, 3f
+       ldr     r6, [r5]
+       add     r6, r5, r6                      @ r6 = mcpm_entry_vectors
+
+mcpm_entry_gated:
+       ldr     r5, [r6, r4, lsl #2]            @ r5 = CPU entry vector
+       cmp     r5, #0
+       wfeeq
+       beq     mcpm_entry_gated
+       pr_dbg  "released\n"
+       bx      r5
+
+       .align  2
+
+3:     .word   mcpm_entry_vectors - .
+
+ENDPROC(mcpm_entry_point)
+
+       .bss
+       .align  5
+
+       .type   mcpm_entry_vectors, #object
+ENTRY(mcpm_entry_vectors)
+       .space  4 * MAX_NR_CLUSTERS * MAX_CPUS_PER_CLUSTER
 
--- /dev/null
+/*
+ * arch/arm/include/asm/mcpm.h
+ *
+ * Created by:  Nicolas Pitre, April 2012
+ * Copyright:   (C) 2012-2013  Linaro 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.
+ */
+
+#ifndef MCPM_H
+#define MCPM_H
+
+/*
+ * Maximum number of possible clusters / CPUs per cluster.
+ *
+ * This should be sufficient for quite a while, while keeping the
+ * (assembly) code simpler.  When this starts to grow then we'll have
+ * to consider dynamic allocation.
+ */
+#define MAX_CPUS_PER_CLUSTER   4
+#define MAX_NR_CLUSTERS                2
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Platform specific code should use this symbol to set up secondary
+ * entry location for processors to use when released from reset.
+ */
+extern void mcpm_entry_point(void);
+
+/*
+ * This is used to indicate where the given CPU from given cluster should
+ * branch once it is ready to re-enter the kernel using ptr, or NULL if it
+ * should be gated.  A gated CPU is held in a WFE loop until its vector
+ * becomes non NULL.
+ */
+void mcpm_set_entry_vector(unsigned cpu, unsigned cluster, void *ptr);
+
+#endif /* ! __ASSEMBLY__ */
+#endif