ARM: rockchip: add cortex-a9 cpuidle support
author黄涛 <huangtao@rock-chips.com>
Thu, 16 Jan 2014 04:15:17 +0000 (12:15 +0800)
committer黄涛 <huangtao@rock-chips.com>
Thu, 16 Jan 2014 04:15:17 +0000 (12:15 +0800)
arch/arm/mach-rockchip/Makefile
arch/arm/mach-rockchip/cpu.h
arch/arm/mach-rockchip/cpuidle.c [new file with mode: 0644]

index 83ae96d69a37e6bfb651b73029534f78cf33a432..edb2865ff4944442e5e263fd042d0ccf9ba20b95 100644 (file)
@@ -1,5 +1,6 @@
 obj-y += common.o
 obj-y += cpu.o
 obj-y += rk3188.o
+obj-$(CONFIG_CPU_IDLE) += cpuidle.o
 obj-$(CONFIG_SMP) += platsmp.o
 obj-$(CONFIG_FIQ_DEBUGGER) += rk_fiq_debugger.o
index 06cef95ed3d2731aeecb1838505e3be34ca042ed..b9820044846e1659b570d5702d6007bb3800abc2 100644 (file)
@@ -3,6 +3,8 @@
 
 extern unsigned long rockchip_soc_id;
 
+static inline bool cpu_is_rockchip(void) { return rockchip_soc_id; }
+
 #define ROCKCHIP_CPU_MASK       0xffff0000
 #define ROCKCHIP_CPU_RK2928     0x29280000
 #define ROCKCHIP_CPU_RK3026     0x30260000
diff --git a/arch/arm/mach-rockchip/cpuidle.c b/arch/arm/mach-rockchip/cpuidle.c
new file mode 100644 (file)
index 0000000..9788b3d
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012-2014 ROCKCHIP, Inc.
+ *
+ * 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/cpuidle.h>
+#include <linux/export.h>
+#include <linux/suspend.h>
+#include <linux/err.h>
+#include <linux/irqchip/arm-gic.h>
+#include <asm/cpuidle.h>
+#include <asm/cputype.h>
+#include <asm/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include "cpu.h"
+
+static void __iomem *gic_cpu_base;
+
+static int rockchip_ca9_cpuidle_enter(struct cpuidle_device *dev,
+               struct cpuidle_driver *drv, int index)
+{
+       do {
+               cpu_do_idle();
+       } while (readl_relaxed(gic_cpu_base + GIC_CPU_HIGHPRI) == 0x3FF);
+       return 0;
+}
+
+static struct cpuidle_driver rockchip_ca9_cpuidle_driver = {
+       .name = "rockchip_ca9_cpuidle",
+       .owner = THIS_MODULE,
+       .states[0] = ARM_CPUIDLE_WFI_STATE,
+       .state_count = 1,
+};
+
+static int __init rockchip_ca9_cpuidle_init(void)
+{
+       struct device_node *np;
+       int ret;
+
+       if (!cpu_is_rockchip())
+               return -ENODEV;
+       if (read_cpuid_part_number() != ARM_CPU_PART_CORTEX_A9)
+               return -ENODEV;
+       np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic");
+       if (!np)
+               return -ENODEV;
+       gic_cpu_base = of_iomap(np, 1);
+       if (!gic_cpu_base) {
+               pr_err("%s: failed to map gic cpu registers\n", __func__);
+               return -EINVAL;
+       }
+       rockchip_ca9_cpuidle_driver.states[0].enter = rockchip_ca9_cpuidle_enter;
+       ret = cpuidle_register(&rockchip_ca9_cpuidle_driver, NULL);
+       if (ret)
+               pr_err("%s: failed to register cpuidle driver: %d\n", __func__, ret);
+
+       return ret;
+}
+
+device_initcall(rockchip_ca9_cpuidle_init);