From patchwork Tue Jun 4 07:17:39 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Simek X-Patchwork-Id: 2657611 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork2.kernel.org (Postfix) with ESMTP id 28D46DF2A1 for ; Tue, 4 Jun 2013 07:39:50 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UjlWh-0005rl-5j; Tue, 04 Jun 2013 07:19:31 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UjlVV-0004FH-EB; Tue, 04 Jun 2013 07:18:13 +0000 Received: from mail-wg0-x230.google.com ([2a00:1450:400c:c00::230]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UjlVS-0004EW-2r for linux-arm-kernel@lists.infradead.org; Tue, 04 Jun 2013 07:18:11 +0000 Received: by mail-wg0-f48.google.com with SMTP id f12so3927562wgh.3 for ; Tue, 04 Jun 2013 00:17:47 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:content-type :x-gm-message-state; bh=FldfO6a2AP3V5dz8HSjFtWOmtwcmg3yJ8SGhOG/pVZY=; b=mUoJYj+a9b0I5GpHhL0Ufw3LSgEBbnDpZTzUGq9woKKSbspCOoA3kHvrLAK3cpwXsy IASccnAOKijl/mObRWAz0KVNTAp/UeJuaVF/hYlu5lMmmNgU9mTQh2DQLbTFye53H44W L2QBp/pc14/keJXOJuSeJTuRKnZ+UP70IV2P+wusblMk/6BSytX/4nv3dSxql3bcxM8K VCUabaV2k3zRU6I4pSxDQcoSG0floXjzXod9m/leCp0TTiaBXssE16ptLSH1vYVHwU8I L2pSxGI+LouHQVtIzHs73kpadCN0gpWsFTqJeTk+ivN5PvWPQ02wuQFp6uMeWaxIdukN G8yw== X-Received: by 10.194.122.225 with SMTP id lv1mr22543374wjb.21.1370330267747; Tue, 04 Jun 2013 00:17:47 -0700 (PDT) Received: from localhost (nat-63.starnet.cz. [178.255.168.63]) by mx.google.com with ESMTPSA id m3sm738067wij.5.2013.06.04.00.17.45 for (version=TLSv1.1 cipher=RC4-SHA bits=128/128); Tue, 04 Jun 2013 00:17:47 -0700 (PDT) From: Michal Simek To: linux-kernel@vger.kernel.org Subject: [PATCH v4] arm: zynq: Add cpuidle support Date: Tue, 4 Jun 2013 09:17:39 +0200 Message-Id: <360abe7d7e8b8a0f785ec846c24fa5cb6658b956.1370330248.git.michal.simek@xilinx.com> X-Mailer: git-send-email 1.8.2.3 X-Gm-Message-State: ALoCoQmFRYd6ouWs9RMZQ+GL/U1Yc4EgFvIBZE/YIg+Iz2aZXhAK4+xPuy5SXmiewLND7SBEgUd3 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130604_031810_407474_2E7289F7 X-CRM114-Status: GOOD ( 25.14 ) X-Spam-Score: -1.2 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.0 T_TVD_MIME_NO_HEADERS BODY: T_TVD_MIME_NO_HEADERS 0.7 MIME_HEADER_CTYPE_ONLY 'Content-Type' found without required MIME headers 0.0 T_MIME_NO_TEXT No (properly identified) text body parts Cc: Josh Cartwright , Michal Simek , Mauro Carvalho Chehab , Arnd Bergmann , linux-pm@vger.kernel.org, Daniel Lezcano , Michal Simek , "Rafael J. Wysocki" , Peter Crosthwaite , Hans Verkuil , Andrew Morton , Steffen Trumtrar , "David S. Miller" , linux-arm-kernel@lists.infradead.org, Cesar Eduardo Barros X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add support for cpuidle. Signed-off-by: Michal Simek Acked-by: Daniel Lezcano --- Changes in v4: - Add record to MAINTAINERS file - Use long license in header + Maintainer record - Remove unused headers - Fix indentations - s/zynq_init_cpuidle/zynq_cpuidle_init/g - use cpuidle_register function - Do not use module_init, use device_initcall instead (Using it as module is not possible because some arm core functions are not exported for modules) Changes in v3: - Move driver to drivers/cpuidle/ - Check zynq compatible string suggested by Arnd - Use zynq_ function prefix because of multiplatform kernel - Incorporate comments from Daniel Lezcano - Rebase on the top of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next Changes in v2: - Fix file header Changes in v1: - It was the part of Zynq core changes https://patchwork.kernel.org/patch/2342511/ MAINTAINERS | 1 + drivers/cpuidle/Kconfig | 6 +++ drivers/cpuidle/Makefile | 1 + drivers/cpuidle/cpuidle-zynq.c | 83 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 drivers/cpuidle/cpuidle-zynq.c -- 1.8.2.3 diff --git a/MAINTAINERS b/MAINTAINERS index 90f45f4..6e4d4e0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1309,6 +1309,7 @@ W: http://wiki.xilinx.com T: git git://git.xilinx.com/linux-xlnx.git S: Supported F: arch/arm/mach-zynq/ +F: drivers/cpuidle/cpuidle-zynq.c ARM64 PORT (AARCH64 ARCHITECTURE) M: Catalin Marinas diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index c4cc27e..8272a08 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -39,4 +39,10 @@ config CPU_IDLE_CALXEDA help Select this to enable cpuidle on Calxeda processors. +config CPU_IDLE_ZYNQ + bool "CPU Idle Driver for Xilinx Zynq processors" + depends on ARCH_ZYNQ + help + Select this to enable cpuidle on Xilinx Zynq processors. + endif diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 0d8bd55..8767a7b 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o obj-$(CONFIG_ARCH_KIRKWOOD) += cpuidle-kirkwood.o +obj-$(CONFIG_CPU_IDLE_ZYNQ) += cpuidle-zynq.o diff --git a/drivers/cpuidle/cpuidle-zynq.c b/drivers/cpuidle/cpuidle-zynq.c new file mode 100644 index 0000000..38e03a1 --- /dev/null +++ b/drivers/cpuidle/cpuidle-zynq.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012-2013 Xilinx + * + * CPU idle support for Xilinx Zynq + * + * based on arch/arm/mach-at91/cpuidle.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see . + * + * The cpu idle uses wait-for-interrupt and RAM self refresh in order + * to implement two idle states - + * #1 wait-for-interrupt + * #2 wait-for-interrupt and RAM self refresh + * + * Maintainer: Michal Simek + */ + +#include +#include +#include +#include +#include +#include + +#define ZYNQ_MAX_STATES 2 + +/* Actual code that puts the SoC in different idle states */ +static int zynq_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + /* Devices must be stopped here */ + cpu_pm_enter(); + + /* Add code for DDR self refresh start */ + cpu_do_idle(); + + /* Add code for DDR self refresh stop */ + cpu_pm_exit(); + + return index; +} + +static struct cpuidle_driver zynq_idle_driver = { + .name = "zynq_idle", + .owner = THIS_MODULE, + .states = { + ARM_CPUIDLE_WFI_STATE, + { + .enter = zynq_enter_idle, + .exit_latency = 10, + .target_residency = 10000, + .flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_TIMER_STOP, + .name = "RAM_SR", + .desc = "WFI and RAM Self Refresh", + }, + }, + .safe_state_index = 0, + .state_count = ZYNQ_MAX_STATES, +}; + +/* Initialize CPU idle by registering the idle states */ +static int __init zynq_cpuidle_init(void) +{ + if (!of_machine_is_compatible("xlnx,zynq-7000")) + return -ENODEV; + + pr_info("Xilinx Zynq CpuIdle Driver started\n"); + + return cpuidle_register(&zynq_idle_driver, NULL); +} + +device_initcall(zynq_cpuidle_init);