diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak
index a784644..8a9482e 100644
--- a/default-configs/mips-softmmu.mak
+++ b/default-configs/mips-softmmu.mak
@@ -31,3 +31,4 @@ CONFIG_MC146818RTC=y
 CONFIG_ISA_TESTDEV=y
 CONFIG_EMPTY_SLOT=y
 CONFIG_MIPS_GIC=y
+CONFIG_MIPS_CPC=y
diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak
index 957508d..27ca662 100644
--- a/default-configs/mips64-softmmu.mak
+++ b/default-configs/mips64-softmmu.mak
@@ -37,3 +37,4 @@ CONFIG_MC146818RTC=y
 CONFIG_ISA_TESTDEV=y
 CONFIG_EMPTY_SLOT=y
 CONFIG_MIPS_GIC=y
+CONFIG_MIPS_CPC=y
diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index 6c1065f..7dfc4cb 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -40,3 +40,4 @@ CONFIG_VT82C686=y
 CONFIG_ISA_TESTDEV=y
 CONFIG_EMPTY_SLOT=y
 CONFIG_MIPS_GIC=y
+CONFIG_MIPS_CPC=y
diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak
index 4633b0b..e02599d 100644
--- a/default-configs/mipsel-softmmu.mak
+++ b/default-configs/mipsel-softmmu.mak
@@ -31,3 +31,4 @@ CONFIG_MC146818RTC=y
 CONFIG_ISA_TESTDEV=y
 CONFIG_EMPTY_SLOT=y
 CONFIG_MIPS_GIC=y
+CONFIG_MIPS_CPC=y
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 7bb14ed..46b3e71 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -43,6 +43,7 @@ obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
 obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
 obj-$(CONFIG_MIPS_GIC) += mips_gcr.o
+obj-$(CONFIG_MIPS_CPC) += mips_cpc.o
 
 obj-$(CONFIG_PVPANIC) += pvpanic.o
 obj-$(CONFIG_EDU) += edu.o
diff --git a/hw/misc/mips_cpc.c b/hw/misc/mips_cpc.c
new file mode 100644
index 0000000..3ea55fb
--- /dev/null
+++ b/hw/misc/mips_cpc.c
@@ -0,0 +1,124 @@
+/*
+ * Cluster Power Controller emulation
+ *
+ * Copyright (c) 2016 Imagination Technologies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+
+#include "hw/misc/mips_cpc.h"
+
+#define CPC_VP_PER_CORE_MAX 4
+#define CPC_VP_RUN_MASK ((1 << CPC_VP_PER_CORE_MAX) - 1)
+
+static void cpc_run_vp(MIPSCPCState *cpc, uint64_t vp_run)
+{
+    CPUState *cs = first_cpu;
+
+    CPU_FOREACH(cs) {
+        uint64_t i = 1ULL << cs->cpu_index;
+        if (i & vp_run & ~cpc->vp_running) {
+            cpu_interrupt(cs, CPU_INTERRUPT_WAKE);
+            cpc->vp_running |= i;
+        }
+    }
+}
+
+static void cpc_stop_vp(MIPSCPCState *cpc, uint64_t vp_stop)
+{
+    CPUState *cs = first_cpu;
+
+    CPU_FOREACH(cs) {
+        uint64_t i = 1ULL << cs->cpu_index;
+        if (i & vp_stop & cpc->vp_running) {
+            cs->halted = 1;
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
+            cpc->vp_running &= ~i;
+        }
+    }
+}
+
+static void cpc_write(void *opaque, hwaddr offset, uint64_t data,
+                      unsigned size)
+{
+    MIPSCPCState *s = opaque;
+
+    switch (offset) {
+    case CPC_CL_BASE_OFS + CPC_VP_RUN_OFS:
+    case CPC_CO_BASE_OFS + CPC_VP_RUN_OFS:
+        cpc_run_vp(s, data & CPC_VP_RUN_MASK);
+        break;
+    case CPC_CL_BASE_OFS + CPC_VP_STOP_OFS:
+    case CPC_CO_BASE_OFS + CPC_VP_STOP_OFS:
+        cpc_stop_vp(s, data & CPC_VP_RUN_MASK);
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
+        break;
+    }
+
+    return;
+}
+
+static uint64_t cpc_read(void *opaque, hwaddr offset, unsigned size)
+{
+    MIPSCPCState *s = opaque;
+
+    switch (offset) {
+    case CPC_CL_BASE_OFS + CPC_VP_RUNNING_OFS:
+    case CPC_CO_BASE_OFS + CPC_VP_RUNNING_OFS:
+        return s->vp_running;
+    default:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
+        return 0;
+    }
+}
+
+static const MemoryRegionOps cpc_ops = {
+    .read = cpc_read,
+    .write = cpc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .max_access_size = 8,
+    },
+};
+
+static void mips_cpc_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    MIPSCPCState *s = MIPS_CPC(obj);
+
+    memory_region_init_io(&s->mr, OBJECT(s), &cpc_ops, s, "mips-cpc",
+                          CPC_ADDRSPACE_SZ);
+    sysbus_init_mmio(sbd, &s->mr);
+}
+
+static const TypeInfo mips_cpc_info = {
+    .name          = TYPE_MIPS_CPC,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(MIPSCPCState),
+    .instance_init = mips_cpc_init,
+};
+
+static void mips_cpc_register_types(void)
+{
+    type_register_static(&mips_cpc_info);
+}
+
+type_init(mips_cpc_register_types)
diff --git a/include/hw/misc/mips_cpc.h b/include/hw/misc/mips_cpc.h
new file mode 100644
index 0000000..2f7f84e
--- /dev/null
+++ b/include/hw/misc/mips_cpc.h
@@ -0,0 +1,45 @@
+/*
+ * Cluster Power Controller emulation
+ *
+ * Copyright (c) 2016 Imagination Technologies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MIPS_CPC_H
+#define MIPS_CPC_H
+
+#define CPC_BASE_ADDR       0x1bde0000ULL
+#define CPC_ADDRSPACE_SZ    0x6000
+
+/* CPC blocks offsets relative to base address */
+#define CPC_CL_BASE_OFS     0x2000
+#define CPC_CO_BASE_OFS     0x4000
+
+/* CPC register offsets relative to block offsets */
+#define CPC_VP_STOP_OFS     0x20
+#define CPC_VP_RUN_OFS      0x28
+#define CPC_VP_RUNNING_OFS  0x30
+
+#define TYPE_MIPS_CPC "mips-cpc"
+#define MIPS_CPC(obj) OBJECT_CHECK(MIPSCPCState, (obj), TYPE_MIPS_CPC)
+
+typedef struct MIPSCPCState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mr;
+    uint64_t vp_running; /* Indicates which VP's are in the run state */
+} MIPSCPCState;
+
+#endif /* MIPS_CPC_H */
